Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. polygon QGraphicsItem shape
Forum Updated to NodeBB v4.3 + New Features

polygon QGraphicsItem shape

Scheduled Pinned Locked Moved Solved General and Desktop
35 Posts 3 Posters 9.8k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K kenchan

    @user4592357
    no, top left and bottom right is probably what you need

    QRectF(QPointF(min_x, min_y), QPointF(max_x, max_y))
    

    http://doc.qt.io/qt-5/qgraphicsitem.html#details

    U Offline
    U Offline
    user4592357
    wrote on last edited by
    #14

    @kenchan
    that's what i was saying

    K 1 Reply Last reply
    0
    • U user4592357

      @kenchan
      that's what i was saying

      K Offline
      K Offline
      kenchan
      wrote on last edited by
      #15

      @user4592357
      :-)

      U 1 Reply Last reply
      0
      • A Offline
        A Offline
        Asperamanca
        wrote on last edited by
        #16

        @user4592357 said in polygon QGraphicsItem shape:

        Not sure that came across:
        The way you posted your code, you actually use bottom/left and top/right to construct the rectangle.

        return QRectF(QPointF(min_x, max_y), QPointF(max_x, min_y))

        1 Reply Last reply
        0
        • K kenchan

          @user4592357
          :-)

          U Offline
          U Offline
          user4592357
          wrote on last edited by user4592357
          #17

          @kenchan
          it's really weird. i set background brush to black of my graphics view, and when i add something like

          item = PolygonItem([QPointF(30, 30), QPointF(50, 50), QPointF(100, 100)])
          

          to the scene, the view becomes white and no item is drawn :(

          here's the scene and view:

          class Scene(QGraphicsScene):
              def __init__(self, parent=None):
                  super(Scene, self).__init__(parent)
          
          class View(QGraphicsView):
              def __init__(self, parent=None):
                  super(View, self).__init__(parent)
                  self.setRenderHint(QPainter.Antialiasing)
                  self.setRenderHint(QPainter.TextAntialiasing)
                  self.setSceneRect(self.scene().sceneRect())
                  self.setBackgroundBrush(QBrush(Qt.black))
          

          this is how i create the scene and view in main window:

          	def __create_scene_and_view(self):
                          self.__scene = Scene(self)
          		self.__view = View(self.__scene)
          		self.__layout_view.show()
          		self.setCentralWidget(self.__view)
          

          some items are drawn correctly, though. for example:

          item = PolygonItem([QPointF(75, -10), QPointF(60, 40), QPointF(110, 10), QPointF(0, 0)])
          

          i noticed, if i add QPointf(0, 0) to the first (non-working) item, it is drawn too

          1 Reply Last reply
          0
          • U Offline
            U Offline
            user4592357
            wrote on last edited by user4592357
            #18

            @kenchan
            hi,

            i fixed the above issue (related to bounding box)

            this is the bound rect now:

            		bb = brect(self.coords)
            
            		if self._hovered:
            			bb.setX(bb.x() - 4)
            			bb.setY(bb.y() - 4)
            			bb.setWidth(bb.width() + 4)
            			bb.setHeight(bb.height() + 4)
            
            		return bb
            

            and this is paint():

            	def paint(self, painter, option, widget):
            		pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5, join=Qt.MiterJoin)
            		pen_line = QPen(QBrush(QColor(Qt.red)), 3, join=Qt.MiterJoin)
            
            		if self._hovered:
            			painter.setPen(pen_outline)
            			painter.drawPolygon(QPolygonF(self.coords))
            
            		painter.setPen(pen_line)
            		painter.drawPolygon(QPolygonF(self.coords))
            

            and these are the results when normal:
            alt text

            and when hovering:
            alt text

            as you can see, the red rectangle has become a lot thicker. why is that?

            i think one reason may be that i'm using coordinates for both normal and highlighted drawing?

            by the way, if i remove the if in bounding rect, i get the "outline" drawn, only within the rect but i need outside it.

            K 1 Reply Last reply
            0
            • U user4592357

              @kenchan
              hi,

              i fixed the above issue (related to bounding box)

              this is the bound rect now:

              		bb = brect(self.coords)
              
              		if self._hovered:
              			bb.setX(bb.x() - 4)
              			bb.setY(bb.y() - 4)
              			bb.setWidth(bb.width() + 4)
              			bb.setHeight(bb.height() + 4)
              
              		return bb
              

              and this is paint():

              	def paint(self, painter, option, widget):
              		pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5, join=Qt.MiterJoin)
              		pen_line = QPen(QBrush(QColor(Qt.red)), 3, join=Qt.MiterJoin)
              
              		if self._hovered:
              			painter.setPen(pen_outline)
              			painter.drawPolygon(QPolygonF(self.coords))
              
              		painter.setPen(pen_line)
              		painter.drawPolygon(QPolygonF(self.coords))
              

              and these are the results when normal:
              alt text

              and when hovering:
              alt text

              as you can see, the red rectangle has become a lot thicker. why is that?

              i think one reason may be that i'm using coordinates for both normal and highlighted drawing?

              by the way, if i remove the if in bounding rect, i get the "outline" drawn, only within the rect but i need outside it.

              K Offline
              K Offline
              kenchan
              wrote on last edited by
              #19

              @user4592357 Hello again,
              I can't see why the red box should get thicker with that code.
              You should probably only offset your bounding box position by -2 if you increase the width and height by 4 (4/2=2 extra pixels on each side).

              U 1 Reply Last reply
              0
              • K kenchan

                @user4592357 Hello again,
                I can't see why the red box should get thicker with that code.
                You should probably only offset your bounding box position by -2 if you increase the width and height by 4 (4/2=2 extra pixels on each side).

                U Offline
                U Offline
                user4592357
                wrote on last edited by
                #20

                @kenchan
                i have played with numbers. setting that to -2 looks worse

                if i remove the if in bounding rect, i get the "outline" drawn, only within the rect but i need outside it.

                K 1 Reply Last reply
                0
                • U user4592357

                  @kenchan
                  i have played with numbers. setting that to -2 looks worse

                  if i remove the if in bounding rect, i get the "outline" drawn, only within the rect but i need outside it.

                  K Offline
                  K Offline
                  kenchan
                  wrote on last edited by kenchan
                  #21

                  @user4592357
                  since you have a width of 3 and 5. assuming the thicker red line in the lower image is width 3 the cyan line looks correct at width 5 having 1 pixel on each side. So, I am thinking that the upper thinner rectangle is incorrectly drawn. It does not look like it has a width of 3 to me. I cannot see why that is though.
                  BTW it made a similar one with C++ and it looks fine.

                  U 1 Reply Last reply
                  0
                  • K kenchan

                    @user4592357
                    since you have a width of 3 and 5. assuming the thicker red line in the lower image is width 3 the cyan line looks correct at width 5 having 1 pixel on each side. So, I am thinking that the upper thinner rectangle is incorrectly drawn. It does not look like it has a width of 3 to me. I cannot see why that is though.
                    BTW it made a similar one with C++ and it looks fine.

                    U Offline
                    U Offline
                    user4592357
                    wrote on last edited by user4592357
                    #22

                    @kenchan
                    red is probably 3, because cyan is 5. but i remove the if from boundingRect()

                    now, when both are drawn from same (x, y), since cyan is 5, is appears to be inside the rect.
                    when i do this, however, the item "goes up" everytime it is hovered:

                    	def paint(self, painter, option, widget):
                    		# create the pens
                    		pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5, join=Qt.MiterJoin)
                    		pen = QPen(QBrush(QColor(Qt.red)), 3, join=Qt.MiterJoin)
                    
                    		if self._hovered:
                    			painter.setPen(pen_outline)
                    			coords = []
                    			for coord in self.coords:
                    				coord.setX(coord.x() - 2)
                    				coord.setY(coord.y() - 2)
                    			 	coords.append(coord)
                    			painter.drawPolygon(QPolygonF(coords))
                    
                    		painter.setPen(pen)
                    		painter.drawPolygon(QPolygonF(self.coords))
                    

                    i need to do something like this i guess - draw a bigger polygon under the original one.
                    but how can i do it, having the coordinates?

                    K 1 Reply Last reply
                    0
                    • U user4592357

                      @kenchan
                      red is probably 3, because cyan is 5. but i remove the if from boundingRect()

                      now, when both are drawn from same (x, y), since cyan is 5, is appears to be inside the rect.
                      when i do this, however, the item "goes up" everytime it is hovered:

                      	def paint(self, painter, option, widget):
                      		# create the pens
                      		pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5, join=Qt.MiterJoin)
                      		pen = QPen(QBrush(QColor(Qt.red)), 3, join=Qt.MiterJoin)
                      
                      		if self._hovered:
                      			painter.setPen(pen_outline)
                      			coords = []
                      			for coord in self.coords:
                      				coord.setX(coord.x() - 2)
                      				coord.setY(coord.y() - 2)
                      			 	coords.append(coord)
                      			painter.drawPolygon(QPolygonF(coords))
                      
                      		painter.setPen(pen)
                      		painter.drawPolygon(QPolygonF(self.coords))
                      

                      i need to do something like this i guess - draw a bigger polygon under the original one.
                      but how can i do it, having the coordinates?

                      K Offline
                      K Offline
                      kenchan
                      wrote on last edited by kenchan
                      #23

                      @user4592357

                      your bounding rect should have either the small rect (when not hovering) or the large rect (when hovering). It might work fine with only the large rect though.
                      My bounding rect looks like this, it works fine.

                      QRectF TestItem2::boundingRect() const
                      {
                          if(hovering)
                              return QRectF(-2, -2, 104, 104);
                          else
                              return QRectF(-1,-1, 102, 102);
                      }
                      

                      my paint function looks like this

                      void TestItem2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
                      {
                          QPen pen5(QBrush(QColor(0,255,255)),5,Qt::SolidLine,Qt::SquareCap,Qt::MiterJoin);
                          QPen pen3(QBrush(QColor(255,0,0)),3,Qt::SolidLine,Qt::SquareCap,Qt::MiterJoin);
                          const QPointF points[4] = {QPointF(0.0,0.0),QPointF(100.0,0.0),QPointF(100.0,100.0),QPointF(0.0,100.0)};
                          if(hovering)
                          {
                              painter->setPen(pen5);
                              painter->drawPolygon(points,4);
                          }
                          painter->setPen(pen3);
                          painter->drawPolygon(points,4);
                      }
                      

                      not quite the same as yours but close enough.
                      I see you have QGraphicsItem.ItemClipsToShape set, that might cause you problems if you don't have your shape function working correctly. Assuming you do have a shape function defined that is.
                      here is what my box looks like

                      U 1 Reply Last reply
                      1
                      • K kenchan

                        @user4592357

                        your bounding rect should have either the small rect (when not hovering) or the large rect (when hovering). It might work fine with only the large rect though.
                        My bounding rect looks like this, it works fine.

                        QRectF TestItem2::boundingRect() const
                        {
                            if(hovering)
                                return QRectF(-2, -2, 104, 104);
                            else
                                return QRectF(-1,-1, 102, 102);
                        }
                        

                        my paint function looks like this

                        void TestItem2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
                        {
                            QPen pen5(QBrush(QColor(0,255,255)),5,Qt::SolidLine,Qt::SquareCap,Qt::MiterJoin);
                            QPen pen3(QBrush(QColor(255,0,0)),3,Qt::SolidLine,Qt::SquareCap,Qt::MiterJoin);
                            const QPointF points[4] = {QPointF(0.0,0.0),QPointF(100.0,0.0),QPointF(100.0,100.0),QPointF(0.0,100.0)};
                            if(hovering)
                            {
                                painter->setPen(pen5);
                                painter->drawPolygon(points,4);
                            }
                            painter->setPen(pen3);
                            painter->drawPolygon(points,4);
                        }
                        

                        not quite the same as yours but close enough.
                        I see you have QGraphicsItem.ItemClipsToShape set, that might cause you problems if you don't have your shape function working correctly. Assuming you do have a shape function defined that is.
                        here is what my box looks like

                        U Offline
                        U Offline
                        user4592357
                        wrote on last edited by
                        #24

                        @kenchan
                        yeah it was that... ugh, thanks.

                        by the way how can i make the outline don't appear "inside"?

                        K 1 Reply Last reply
                        0
                        • U user4592357

                          @kenchan
                          yeah it was that... ugh, thanks.

                          by the way how can i make the outline don't appear "inside"?

                          K Offline
                          K Offline
                          kenchan
                          wrote on last edited by
                          #25

                          @user4592357
                          You want the highlight outline not to show inside the red box?

                          U 1 Reply Last reply
                          0
                          • K kenchan

                            @user4592357
                            You want the highlight outline not to show inside the red box?

                            U Offline
                            U Offline
                            user4592357
                            wrote on last edited by
                            #26

                            @kenchan
                            yes

                            K 1 Reply Last reply
                            0
                            • U user4592357

                              @kenchan
                              yes

                              K Offline
                              K Offline
                              kenchan
                              wrote on last edited by kenchan
                              #27

                              @user4592357
                              hmm. easiest way with a simple rectangle is to just draw a line of width 1 around the outside of your red one.
                              Same thing if it is more complex polygon but tricky to offset the points in the correct direction.
                              alt text

                              U 1 Reply Last reply
                              0
                              • K kenchan

                                @user4592357
                                hmm. easiest way with a simple rectangle is to just draw a line of width 1 around the outside of your red one.
                                Same thing if it is more complex polygon but tricky to offset the points in the correct direction.
                                alt text

                                U Offline
                                U Offline
                                user4592357
                                wrote on last edited by
                                #28

                                @kenchan
                                that's actually what i wanted to do - but the problem is i don't know when to add and when to subtract from coordinate:

                                	def paint(self, painter, option, widget):
                                		""" Mandatory override of base class. """
                                
                                		# create the pens
                                		pen_outline = QPen(QBrush(QColor(Qt.cyan)), 1, join=Qt.MiterJoin)
                                		pen = QPen(QBrush(QColor(Qt.red)), 2, join=Qt.MiterJoin)
                                
                                		if self._hovered:
                                			painter.setPen(pen_outline)
                                			
                                			for pt in range(len(self.coords)):
                                				coord1 = self.coords[pt % len(self.coords)] - QPointF(1, 1)
                                				coord2 = self.coords[(pt + 1) % len(self.coords)] - QPointF(1, 1)
                                				painter.drawLine(coord1, coord2)
                                			# painter.drawPolygon(QPolygonF(self.coords))
                                
                                		painter.setPen(pen)
                                		painter.drawPolygon(QPolygonF(self.coords))
                                

                                result:
                                alt text

                                K 1 Reply Last reply
                                0
                                • U user4592357

                                  @kenchan
                                  that's actually what i wanted to do - but the problem is i don't know when to add and when to subtract from coordinate:

                                  	def paint(self, painter, option, widget):
                                  		""" Mandatory override of base class. """
                                  
                                  		# create the pens
                                  		pen_outline = QPen(QBrush(QColor(Qt.cyan)), 1, join=Qt.MiterJoin)
                                  		pen = QPen(QBrush(QColor(Qt.red)), 2, join=Qt.MiterJoin)
                                  
                                  		if self._hovered:
                                  			painter.setPen(pen_outline)
                                  			
                                  			for pt in range(len(self.coords)):
                                  				coord1 = self.coords[pt % len(self.coords)] - QPointF(1, 1)
                                  				coord2 = self.coords[(pt + 1) % len(self.coords)] - QPointF(1, 1)
                                  				painter.drawLine(coord1, coord2)
                                  			# painter.drawPolygon(QPolygonF(self.coords))
                                  
                                  		painter.setPen(pen)
                                  		painter.drawPolygon(QPolygonF(self.coords))
                                  

                                  result:
                                  alt text

                                  K Offline
                                  K Offline
                                  kenchan
                                  wrote on last edited by kenchan
                                  #29

                                  @user4592357
                                  ah yes, that is the tricky bit :-). you want the point that is 1 pixel beyond the end of each line segment and offset 1 pixel in the normal direction to that line segment, assuming your lines segments progress in the same orderly direction around your polygon. Think vectors... there are several ways to think about it in terms of vectors. The outward pointing average normal vector to the line segments that meet at the corner, etc.

                                  U 1 Reply Last reply
                                  0
                                  • K kenchan

                                    @user4592357
                                    ah yes, that is the tricky bit :-). you want the point that is 1 pixel beyond the end of each line segment and offset 1 pixel in the normal direction to that line segment, assuming your lines segments progress in the same orderly direction around your polygon. Think vectors... there are several ways to think about it in terms of vectors. The outward pointing average normal vector to the line segments that meet at the corner, etc.

                                    U Offline
                                    U Offline
                                    user4592357
                                    wrote on last edited by
                                    #30

                                    @kenchan
                                    oh sorry, but i don't get what you mean

                                    K 1 Reply Last reply
                                    0
                                    • U user4592357

                                      @kenchan
                                      oh sorry, but i don't get what you mean

                                      K Offline
                                      K Offline
                                      kenchan
                                      wrote on last edited by
                                      #31

                                      @user4592357
                                      Well, you must devise an algorithm to determine how to offset of the polygon outwards by one pixel. I come from a CAD/CG background so I think about that in term of direction vectors etc. Sorry but I don't have time right now to do that for you, you should probably do that yourself :-). Since we are only talking about one pixel offset I could imagine a simple lookup table where you select how to offset the pixel depending on the direction of your line segments in the local coordinate system of the polygon i.e. coordinates increase from top left down to bottom right... your line segments are pointing in some direction in relation to that coordinate system. But this kind of thing has nothing to do with Qt because you know how to draw it with Qt once you have decided which pixel to use :-).

                                      U 1 Reply Last reply
                                      2
                                      • K kenchan

                                        @user4592357
                                        Well, you must devise an algorithm to determine how to offset of the polygon outwards by one pixel. I come from a CAD/CG background so I think about that in term of direction vectors etc. Sorry but I don't have time right now to do that for you, you should probably do that yourself :-). Since we are only talking about one pixel offset I could imagine a simple lookup table where you select how to offset the pixel depending on the direction of your line segments in the local coordinate system of the polygon i.e. coordinates increase from top left down to bottom right... your line segments are pointing in some direction in relation to that coordinate system. But this kind of thing has nothing to do with Qt because you know how to draw it with Qt once you have decided which pixel to use :-).

                                        U Offline
                                        U Offline
                                        user4592357
                                        wrote on last edited by
                                        #32

                                        @kenchan
                                        okay, at first i didn't get that i needed to consider the direction of the vector.

                                        and by the way, i have reimplemented view's wheelEvent but i also need scrollbars to appear when needed:

                                        	def wheelEvent(self, event):
                                        		factor = 1.41 ** (event.angleDelta().y() / 240.0) # ** is pow
                                        		self.scale(factor, factor)
                                                        # call base version
                                        		super(View, self).wheelEvent(event)
                                        

                                        now scrollbars only appear when, say i have a few items, when i scroll enough and they won't fit in view, only then. i think it's because i set view's scene rect to scene's rect?

                                        this is view setup:

                                        	def __init__(self, parent=None):
                                        		super(View, self).__init__(parent)
                                        		self.setDragMode(QGraphicsView.NoDrag)
                                        		self.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)
                                        		self.setSceneRect(self.scene().sceneRect())
                                        		self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
                                        		self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
                                        
                                        K 1 Reply Last reply
                                        0
                                        • U user4592357

                                          @kenchan
                                          okay, at first i didn't get that i needed to consider the direction of the vector.

                                          and by the way, i have reimplemented view's wheelEvent but i also need scrollbars to appear when needed:

                                          	def wheelEvent(self, event):
                                          		factor = 1.41 ** (event.angleDelta().y() / 240.0) # ** is pow
                                          		self.scale(factor, factor)
                                                          # call base version
                                          		super(View, self).wheelEvent(event)
                                          

                                          now scrollbars only appear when, say i have a few items, when i scroll enough and they won't fit in view, only then. i think it's because i set view's scene rect to scene's rect?

                                          this is view setup:

                                          	def __init__(self, parent=None):
                                          		super(View, self).__init__(parent)
                                          		self.setDragMode(QGraphicsView.NoDrag)
                                          		self.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)
                                          		self.setSceneRect(self.scene().sceneRect())
                                          		self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
                                          		self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
                                          
                                          K Offline
                                          K Offline
                                          kenchan
                                          wrote on last edited by
                                          #33

                                          @user4592357
                                          you have the scroll bar policy set as Qt.ScrollBarAsNeeded so that is what it is doing for you.
                                          Is that not what you wanted?

                                          U 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved