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
QtWS25 Last Chance

polygon QGraphicsItem shape

Scheduled Pinned Locked Moved Solved General and Desktop
35 Posts 3 Posters 9.3k 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 Offline
    U Offline
    user4592357
    wrote on last edited by
    #1

    i have a QGraphicsItem sublcass where i add some members, call it GraphicsItem.
    then i derive from this class a Polygon class. notice i don't derive from both QGraphicsPolygonItem and GraphicsItem.

    in my Polygon class i reimplemented boundingRect() and paint():

    boundingRect():
        return the bounding rectangle for the polygon
    

    this works. but i also need to be able do things when the item is hovered, clicked, double-clicked.
    i have these in GraphicsItem class:

    	void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
            {
    		prepareGeometryChange();
    		m_hovered = true;
    		QGraphicsItem::hoverEnterEvent(event);
            }
    
    	void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
            {
    		prepareGeometryChange();
    		m_hovered = false;
    		QGraphicsItem::hoverLeaveEvent(event);
            }
    
    	void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
            {
    		qDebug() << "double clicked";
    		QGraphicsItem::hoverLeaveEvent(event);
            }
    

    and in Polygon class i do (for drawing outline when hovered):

    	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
            {
    		auto pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5);
    		auto pen_line = QPen(QBrush(QColor(Qt.red)), 3);
    
    		if (m_hovered)
                    {
    			painter->setPen(pen_outline);
    			painter->drawPolygon(QPolygonF(m_coords));
                    }
    
    		painter->setPen(pen_line);
    		painter->drawPolygon(QPolygonF(m_coords));
            }
    

    however, the outline isn't drawn and the "double clicked" isn't output.

    should i reimplement shape() too for this to work? and if so, how?

    K 1 Reply Last reply
    0
    • U user4592357

      i have a QGraphicsItem sublcass where i add some members, call it GraphicsItem.
      then i derive from this class a Polygon class. notice i don't derive from both QGraphicsPolygonItem and GraphicsItem.

      in my Polygon class i reimplemented boundingRect() and paint():

      boundingRect():
          return the bounding rectangle for the polygon
      

      this works. but i also need to be able do things when the item is hovered, clicked, double-clicked.
      i have these in GraphicsItem class:

      	void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
              {
      		prepareGeometryChange();
      		m_hovered = true;
      		QGraphicsItem::hoverEnterEvent(event);
              }
      
      	void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
              {
      		prepareGeometryChange();
      		m_hovered = false;
      		QGraphicsItem::hoverLeaveEvent(event);
              }
      
      	void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
              {
      		qDebug() << "double clicked";
      		QGraphicsItem::hoverLeaveEvent(event);
              }
      

      and in Polygon class i do (for drawing outline when hovered):

      	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
              {
      		auto pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5);
      		auto pen_line = QPen(QBrush(QColor(Qt.red)), 3);
      
      		if (m_hovered)
                      {
      			painter->setPen(pen_outline);
      			painter->drawPolygon(QPolygonF(m_coords));
                      }
      
      		painter->setPen(pen_line);
      		painter->drawPolygon(QPolygonF(m_coords));
              }
      

      however, the outline isn't drawn and the "double clicked" isn't output.

      should i reimplement shape() too for this to work? and if so, how?

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

      @user4592357
      Yes I think you should implement the shape function.
      Can you post all the code for these classes (at least enough to test it anyway)

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

        Are you sure the boundingRect() implementation is correct, and uses the right coordinate system?

        The default shape() implementation would use the boundingRect(). So you need to reimplement shape() if you e.g. want to react only to double clicks into the polygon area. However, the default implementation should be sufficient that the doubleClick works in principle.

        1 Reply Last reply
        0
        • K kenchan

          @user4592357
          Yes I think you should implement the shape function.
          Can you post all the code for these classes (at least enough to test it anyway)

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

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

                                          • Login

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