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 Update on Monday, May 27th 2025

polygon QGraphicsItem shape

Scheduled Pinned Locked Moved Solved General and Desktop
35 Posts 3 Posters 9.4k Views
  • 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.
  • U user4592357

    @kenchan here it is and sorry it's in python.

    the base class:

    class Item(QGraphicsItem):
    	def __init__(self, coords, parent=None):
    		super(Item, self).__init__(parent)
    
    		# set the properties
    		self.coords = coords
    		self._hovered = False
    		
    		self.setAcceptHoverEvents(True)
    		self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemClipsToShape)
    
    	def hoverEnterEvent(self, event):
    		self.prepareGeometryChange()
    		self._hovered = True
    		super(Item, self).hoverEnterEvent(event)
    
    	def hoverLeaveEvent(self, event):
    		self.prepareGeometryChange()
    		self._hovered = False
    		super(Item, self).hoverLeaveEvent(event)
    
    	def mouseDoubleClickEvent(self, event):
    		print("dbl click")
    		super(Item, self).mouseDoubleClickEvent(event)
    

    the polygon class:

    class PolygonItem(ErroItem):
    	def __init__(self, coords, parent=None):
    		""" Initialize the polygon item. """
    		super(PolygonItem, self).__init__(coords, parent)
    
    	def boundingRect(self):
    		return bounding_rect(self.coords)
    
    	def paint(self, painter, option, widget):
    		""" Mandatory override of base class. """
    		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))
    
    K Offline
    K Offline
    kenchan
    wrote on last edited by
    #5

    @user4592357
    Thanks for posting the code As you probably guessed I don't use Qt python :-). I am sure there are python experts who can give you advice.
    I can consider its behaviour in terms of C++ though.

    U 1 Reply Last reply
    0
    • K kenchan

      @user4592357
      Thanks for posting the code As you probably guessed I don't use Qt python :-). I am sure there are python experts who can give you advice.
      I can consider its behaviour in terms of C++ though.

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

      @kenchan
      yeah i mean there's nothing specific to python here

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

        How is the function "bounding_rect(self.coords)" implemented?

        U 1 Reply Last reply
        0
        • A Asperamanca

          How is the function "bounding_rect(self.coords)" implemented?

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

          @Asperamanca

              max_x = max_y = -inf
              min_x = min_y = inf
          
              # calculate min/max x/y values
              for point in points:
                  if point.x() > max_x:
                      max_x = point.x()
                  elif point.x() < min_x:
                      min_x = point.x()
                  if point.y() > max_y:
                      max_y = point.y()
                  elif point.y() < min_y:
                      min_y = point.y()
          
              # construct a rectangle out of those coordinates        
              return QRectF(QPointF(min_x, max_y), QPointF(max_x, min_y))
          
          1 Reply Last reply
          0
          • A Offline
            A Offline
            Asperamanca
            wrote on last edited by
            #9

            Not sure this is related to your issue, but is there any specific reason you flip the y axis?

            U 1 Reply Last reply
            0
            • A Asperamanca

              Not sure this is related to your issue, but is there any specific reason you flip the y axis?

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

              @Asperamanca
              what do you mean by flip? for bounding rect i take top left and bottom right coordinates of the rect

              K 1 Reply Last reply
              0
              • U user4592357

                @Asperamanca
                what do you mean by flip? for bounding rect i take top left and bottom right coordinates of the rect

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

                @user4592357
                GraphicItem coordinates are origin at top left and positive axis down to the right. So your Y axis is flipped.
                Unless you changed it somewhere else.

                U 1 Reply Last reply
                0
                • K kenchan

                  @user4592357
                  GraphicItem coordinates are origin at top left and positive axis down to the right. So your Y axis is flipped.
                  Unless you changed it somewhere else.

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

                  @kenchan
                  oh right, so i need to take bottom left and top right points?

                  K 1 Reply Last reply
                  0
                  • U user4592357

                    @kenchan
                    oh right, so i need to take bottom left and top right points?

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

                    @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 1 Reply Last reply
                    0
                    • 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

                                          • Login

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