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. Adding QGraphicsItem at View Coordinates
Forum Updated to NodeBB v4.3 + New Features

Adding QGraphicsItem at View Coordinates

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 4 Posters 1.7k 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.
  • S Offline
    S Offline
    Strangelove
    wrote on last edited by
    #1

    Hi,

    What's the simplest way to add a QGraphicsItem to a QGraphicsScene so that it's always visible at a fixed, absolute position relative to the view coordinates (such as a FPS counter)?

    I can't understand from the documentation if I'm supposed to juggle stuff around with map from/to scene or if there's a simpler way.

    Thanks.

    JonBJ eyllanescE 2 Replies Last reply
    0
    • S Strangelove

      Hi,

      What's the simplest way to add a QGraphicsItem to a QGraphicsScene so that it's always visible at a fixed, absolute position relative to the view coordinates (such as a FPS counter)?

      I can't understand from the documentation if I'm supposed to juggle stuff around with map from/to scene or if there's a simpler way.

      Thanks.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @Strangelove
      You want to show something at, say, the top-left of any view, regardless of where on the scene the view is showing, like say a counter or a logo, right? And probably independent of any zooming? I hope I'm right, but this doesn't sound line a QGraphicsItem to me. That is an object on the scene. If you did that, you'd have to move it as the view moved around the scene? You just have an "artefact" on the view? I assume the would be best implemented via QGraphicsView::drawForeground():

      Draws the foreground of the scene using painter, after the background and all items are drawn. Reimplement this function to provide a custom foreground for this view.

      Actually, if you want it present in any view, same principle but on the scene QGraphicsScene::drawForeground():

      Draws the foreground of the scene using painter, after the background and all items have been drawn. Reimplement this function to provide a custom foreground for the scene.

      But I have feeling you want it on the view....

      S 1 Reply Last reply
      0
      • S Strangelove

        Hi,

        What's the simplest way to add a QGraphicsItem to a QGraphicsScene so that it's always visible at a fixed, absolute position relative to the view coordinates (such as a FPS counter)?

        I can't understand from the documentation if I'm supposed to juggle stuff around with map from/to scene or if there's a simpler way.

        Thanks.

        eyllanescE Offline
        eyllanescE Offline
        eyllanesc
        wrote on last edited by
        #3

        @Strangelove There are several alternative solutions but it will depend on your objective of that item.

        • A possible solution is to do the custom painting (they are not QGraphicsItems) override the drawForeground method.

        • Instead of using a QGraphicsItem you can use a QWidget on top of the viewport(parent):

        FooWidget *widget = new FooWidget(graphicsView->viewport());
        

        OR

        FooWidget *widget = new FooWidget()
        widget->setParent(graphicsView->viewport());
        

        If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

        1 Reply Last reply
        0
        • JonBJ JonB

          @Strangelove
          You want to show something at, say, the top-left of any view, regardless of where on the scene the view is showing, like say a counter or a logo, right? And probably independent of any zooming? I hope I'm right, but this doesn't sound line a QGraphicsItem to me. That is an object on the scene. If you did that, you'd have to move it as the view moved around the scene? You just have an "artefact" on the view? I assume the would be best implemented via QGraphicsView::drawForeground():

          Draws the foreground of the scene using painter, after the background and all items are drawn. Reimplement this function to provide a custom foreground for this view.

          Actually, if you want it present in any view, same principle but on the scene QGraphicsScene::drawForeground():

          Draws the foreground of the scene using painter, after the background and all items have been drawn. Reimplement this function to provide a custom foreground for the scene.

          But I have feeling you want it on the view....

          S Offline
          S Offline
          Strangelove
          wrote on last edited by Strangelove
          #4

          @JonB said in Adding QGraphicsItem at View Coordinates:

          like say a counter or a logo, right?

          Right.

          I've tried the following but apparently I misunderstood the purpose of drawForeground, as this object is transformed together with the scene like any other object:

              def drawForeground(self, painter: QPainter, rect):
                  painter.setPen(QPen(QColor('white')))
                  painter.drawEllipse(0, 0, 50, 50)
                  return super().drawForeground(painter, rect)
          

          Isn't there a simple way to just draw a static stenciled item using view coordinates?

          JonBJ eyllanescE 2 Replies Last reply
          0
          • S Strangelove

            @JonB said in Adding QGraphicsItem at View Coordinates:

            like say a counter or a logo, right?

            Right.

            I've tried the following but apparently I misunderstood the purpose of drawForeground, as this object is transformed together with the scene like any other object:

                def drawForeground(self, painter: QPainter, rect):
                    painter.setPen(QPen(QColor('white')))
                    painter.drawEllipse(0, 0, 50, 50)
                    return super().drawForeground(painter, rect)
            

            Isn't there a simple way to just draw a static stenciled item using view coordinates?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @Strangelove said in Adding QGraphicsItem at View Coordinates:

            as this object is transformed together with the scene like any other object

            I don't know about this, you may have to untransform. But is this an override of QGraphicsView.drawForeground or of QGraphicsScene.drawForeground?

            As a small point, because you want yours on top of anything I would call super().drawForeground(painter, rect) base class before drawing your own stuff rather than afterwards.

            S 1 Reply Last reply
            0
            • JonBJ JonB

              @Strangelove said in Adding QGraphicsItem at View Coordinates:

              as this object is transformed together with the scene like any other object

              I don't know about this, you may have to untransform. But is this an override of QGraphicsView.drawForeground or of QGraphicsScene.drawForeground?

              As a small point, because you want yours on top of anything I would call super().drawForeground(painter, rect) base class before drawing your own stuff rather than afterwards.

              S Offline
              S Offline
              Strangelove
              wrote on last edited by
              #6

              @JonB said in Adding QGraphicsItem at View Coordinates:

              But is this an override of QGraphicsView.drawForeground or of QGraphicsScene.drawForeground

              It's an override of QGraphicsView. I don't know why it's using scene coordinates.

              1 Reply Last reply
              0
              • LeoCL Offline
                LeoCL Offline
                LeoC
                wrote on last edited by
                #7

                I am still not very familiar with the graphics stuff in Qt but what about just using something like QRec?
                You just put some coordinates to it and then draw it with QPainter.

                QRect::QRect(int x, int y, int width, int height)
                

                https://doc.qt.io/qt-5/qrect.html

                S 1 Reply Last reply
                0
                • LeoCL LeoC

                  I am still not very familiar with the graphics stuff in Qt but what about just using something like QRec?
                  You just put some coordinates to it and then draw it with QPainter.

                  QRect::QRect(int x, int y, int width, int height)
                  

                  https://doc.qt.io/qt-5/qrect.html

                  S Offline
                  S Offline
                  Strangelove
                  wrote on last edited by Strangelove
                  #8

                  @LeoC I added the following to the QWidget that contains the QGraphicsView (inside a BoxLayout), but no line was added to the widget:

                      def paintEvent(self, event):
                          qp = QPainter()
                          qp.begin(self)
                          pen = QPen()
                          pen.setColor('red')
                          qp.setPen(pen)
                          qp.drawText(20, 15, 'HELLO')
                          qp.end()
                  

                  I tried adding it to the QGraphicsView itself but, as I was expecting, the result was worse (the view stopped working and didn't display anything at all).

                  EDIT: The text does get drawn on the part of the widget which is just outside the QGraphicsView (the blue grid in the screenshot below). It doesn't get draw on the view itself (which is what I'm trying to achieve).

                  Screenshot 2021-07-29 at 23.59.38.jpg

                  1 Reply Last reply
                  0
                  • S Strangelove

                    @JonB said in Adding QGraphicsItem at View Coordinates:

                    like say a counter or a logo, right?

                    Right.

                    I've tried the following but apparently I misunderstood the purpose of drawForeground, as this object is transformed together with the scene like any other object:

                        def drawForeground(self, painter: QPainter, rect):
                            painter.setPen(QPen(QColor('white')))
                            painter.drawEllipse(0, 0, 50, 50)
                            return super().drawForeground(painter, rect)
                    

                    Isn't there a simple way to just draw a static stenciled item using view coordinates?

                    eyllanescE Offline
                    eyllanescE Offline
                    eyllanesc
                    wrote on last edited by
                    #9

                    @Strangelove QPainter uses the coordinates of the scene for painting so the QRect (and any geometric elements) you use must be converted to that coordinate system.

                    from PyQt5 import QtCore, QtGui, QtWidgets
                    
                    
                    class GraphicsView(QtWidgets.QGraphicsView):
                        def drawForeground(self, painter, rect):
                            super().drawForeground(painter, rect)
                            rect = QtCore.QRect(0, 0, 50, 50)
                            point = QtCore.QPoint(20, 15)
                    
                            painter.setPen(QtGui.QPen(QtGui.QColor("white")))
                            painter.drawEllipse(self.mapToScene(rect).boundingRect())
                            painter.drawText(self.mapToScene(point), "HELLO")
                    
                    
                    def main():
                        import sys
                    
                        app = QtWidgets.QApplication(sys.argv)
                        scene = QtWidgets.QGraphicsScene()
                        view = GraphicsView(scene)
                        view.show()
                        sys.exit(app.exec_())
                    
                    
                    if __name__ == "__main__":
                        main()
                    

                    If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                    1 Reply Last reply
                    3

                    • Login

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