Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. QGraphicsView manually draw scene items
Forum Updated to NodeBB v4.3 + New Features

QGraphicsView manually draw scene items

Scheduled Pinned Locked Moved Solved Qt for Python
4 Posts 3 Posters 978 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.
  • L Offline
    L Offline
    LeonLambert
    wrote on last edited by
    #1

    I would like to know how to manually paint scene items in a QGraphicsView. My issues is if i add items with pixmaps they pixelate when zoomed in. If i could manually draw them then i could adjust the scaling appropriately. I have no issue doing this sort of thing in html canvases using javascript. I am just playing with PyQt to try and do the same thing in python. It seemed the QGraphicsView used to have a drawItems method but it no longer seems to exist so need to find out how to do it now. Following is a small demo that puts a pixmap into a label. The image i am using is 1085 x 1085 so plenty of resolution. As you can see when you zoom in the image pixelates making it look ugly. If i could manually draw it I should be able to rescale the image.

    I am trying to do something similar to a mapping app with picture widgets on top the map. As i zoom in the detail on the pictures should get better not worse. Any help would be appreciated.

    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtCore import Qt
    
    
    class MyQGraphicsView(QtWidgets.QGraphicsView):
        def __init__(self, *args):
            super(MyQGraphicsView, self).__init__(*args)
            self.zoom = 1
            pass
    
        def wheelEvent(self, event):
            delta = event.angleDelta().y() / 120
            if delta > 0:
                self.zoom *= 1.05
            elif delta < 0:
                self.zoom /= 1.05
            self.transform()
    
        def transform(self):
            self.setTransform(QtGui.QTransform().scale(self.zoom, self.zoom))
    
        def setZoom(self, newZoom):
            self.zoom = newZoom
            self.transform()
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.resize(800, 600)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
            self.scene = QtWidgets.QGraphicsScene(self.centralwidget)
            self.graphicsView = MyQGraphicsView(self.scene)
            self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1)
            MainWindow.setCentralWidget(self.centralwidget)
            self.graphicsView.setSceneRect(0, 0, 2000, 2000)
            self.graphicsView.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
    
            pix = QtGui.QPixmap('./image/test.jpg')
            pix.scaled(50, 50, Qt.KeepAspectRatio)
            wig = QtWidgets.QLabel()
            wig.setGeometry(0,0,50,50)
            wig.setPixmap(pix)
            wig.setAlignment(QtCore.Qt.AlignCenter)
            wig.setScaledContents(True)
            wig.setMinimumSize(1, 1)
    
            proxy = QtWidgets.QGraphicsProxyWidget()
            proxy.setWidget(wig)
            self.scene.addItem(proxy)
            proxy.setPos(200, 200)
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        MainWindow = QtWidgets.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())
    

    test.jpg

    JonBJ 1 Reply Last reply
    0
    • L LeonLambert

      I would like to know how to manually paint scene items in a QGraphicsView. My issues is if i add items with pixmaps they pixelate when zoomed in. If i could manually draw them then i could adjust the scaling appropriately. I have no issue doing this sort of thing in html canvases using javascript. I am just playing with PyQt to try and do the same thing in python. It seemed the QGraphicsView used to have a drawItems method but it no longer seems to exist so need to find out how to do it now. Following is a small demo that puts a pixmap into a label. The image i am using is 1085 x 1085 so plenty of resolution. As you can see when you zoom in the image pixelates making it look ugly. If i could manually draw it I should be able to rescale the image.

      I am trying to do something similar to a mapping app with picture widgets on top the map. As i zoom in the detail on the pictures should get better not worse. Any help would be appreciated.

      from PyQt5 import QtCore, QtGui, QtWidgets
      from PyQt5.QtCore import Qt
      
      
      class MyQGraphicsView(QtWidgets.QGraphicsView):
          def __init__(self, *args):
              super(MyQGraphicsView, self).__init__(*args)
              self.zoom = 1
              pass
      
          def wheelEvent(self, event):
              delta = event.angleDelta().y() / 120
              if delta > 0:
                  self.zoom *= 1.05
              elif delta < 0:
                  self.zoom /= 1.05
              self.transform()
      
          def transform(self):
              self.setTransform(QtGui.QTransform().scale(self.zoom, self.zoom))
      
          def setZoom(self, newZoom):
              self.zoom = newZoom
              self.transform()
      
      
      class Ui_MainWindow(object):
          def setupUi(self, MainWindow):
              MainWindow.resize(800, 600)
              self.centralwidget = QtWidgets.QWidget(MainWindow)
              self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
              self.scene = QtWidgets.QGraphicsScene(self.centralwidget)
              self.graphicsView = MyQGraphicsView(self.scene)
              self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1)
              MainWindow.setCentralWidget(self.centralwidget)
              self.graphicsView.setSceneRect(0, 0, 2000, 2000)
              self.graphicsView.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
      
              pix = QtGui.QPixmap('./image/test.jpg')
              pix.scaled(50, 50, Qt.KeepAspectRatio)
              wig = QtWidgets.QLabel()
              wig.setGeometry(0,0,50,50)
              wig.setPixmap(pix)
              wig.setAlignment(QtCore.Qt.AlignCenter)
              wig.setScaledContents(True)
              wig.setMinimumSize(1, 1)
      
              proxy = QtWidgets.QGraphicsProxyWidget()
              proxy.setWidget(wig)
              self.scene.addItem(proxy)
              proxy.setPos(200, 200)
      
      if __name__ == "__main__":
          import sys
          app = QtWidgets.QApplication(sys.argv)
          MainWindow = QtWidgets.QMainWindow()
          ui = Ui_MainWindow()
          ui.setupUi(MainWindow)
          MainWindow.show()
          sys.exit(app.exec_())
      

      test.jpg

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

      @LeonLambert said in QGraphicsView manually draw scene items:

      It seemed the QGraphicsView used to have a drawItems method but it no longer seems to exist

      I don't have a comment on pixmap/scaling, but you can draw whatever you like via e.g. void QGraphicsScene::drawForeground(QPainter *painter, const QRectF &rect) (or QGraphicsView has this too). You override that and it gives you a QPainter which has all your draw...() routines.

      1 Reply Last reply
      0
      • F Offline
        F Offline
        friedemannkleint
        wrote on last edited by
        #3

        The colliding mice example shows how to create custom items: https://doc.qt.io/qtforpython-6/examples/example_widgets_graphicsview_collidingmice.html

        1 Reply Last reply
        1
        • L Offline
          L Offline
          LeonLambert
          wrote on last edited by
          #4

          The colliding mice help by showing me how to use a QGraphicsItem. I made a few tweaks and came up with this code that seems to work. Thanks for your help.

          import typing
          from PyQt5 import QtCore, QtGui, QtWidgets
          from PyQt5.QtCore import Qt
          from PyQt5.QtWidgets import QWidget
          
          
          class MyQGraphicsView(QtWidgets.QGraphicsView):
              def __init__(self, *args):
                  super(MyQGraphicsView, self).__init__(*args)
                  self.zoom = 1
                  self.gridSize = 50
                  pass
          
              def wheelEvent(self, event):
                  delta = event.angleDelta().y() / 120
                  if delta > 0:
                      self.zoom *= 1.05
                  elif delta < 0:
                      self.zoom /= 1.05
                  self.transform()
          
              def transform(self):
                  self.setTransform(QtGui.QTransform().scale(self.zoom, self.zoom))
          
              def setZoom(self, newZoom):
                  self.zoom = newZoom
                  self.transform()
          
              def getScaledGridSize(self):
                  return int(self.gridSize * self.zoom)
          
          
          class MyItem(QtWidgets.QGraphicsItem):
          
              def __init__(self, imagePath, view, *args):
                  super(MyItem, self).__init__(*args)
                  self.image = QtGui.QImage(imagePath)
                  self.pixMap = None
                  self.view = view
                  self.scaledGridSize = 0
          
              def boundingRect(self):
                  return QtCore.QRectF(0, 0, 50, 50)
          
              def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionGraphicsItem',
                        widget: typing.Optional[QWidget] = ...) -> None:
                  gridSize = self.view.getScaledGridSize()
                  if gridSize != self.scaledGridSize:
                      self.scaledGridSize = gridSize
                      pixMap = QtGui.QPixmap.fromImage(self.image)
                      self.pixMap = pixMap.scaled(self.scaledGridSize,
                                        self.scaledGridSize, Qt.KeepAspectRatio,
                                        Qt.SmoothTransformation)
                  painter.drawPixmap(0, 0, self.pixMap)
          
          
          class Ui_MainWindow(object):
              
              def setupUi(self, MainWindow):
                  MainWindow.resize(800, 600)
                  self.centralwidget = QtWidgets.QWidget(MainWindow)
                  self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
                  self.scene = QtWidgets.QGraphicsScene(self.centralwidget)
                  self.graphicsView = MyQGraphicsView(self.scene)
                  self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1)
                  MainWindow.setCentralWidget(self.centralwidget)
                  self.graphicsView.setSceneRect(0, 0, 2000, 2000)
                  self.graphicsView.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
                  wig = MyItem('../image/test.jpg', self.graphicsView)
                  self.scene.addItem(wig)
                  wig.setPos(200, 200)
          
          if __name__ == "__main__":
              import sys
              app = QtWidgets.QApplication(sys.argv)
              MainWindow = QtWidgets.QMainWindow()
              ui = Ui_MainWindow()
              ui.setupUi(MainWindow)
              MainWindow.show()
              sys.exit(app.exec_())
          
          
          1 Reply Last reply
          0
          • L LeonLambert has marked this topic as solved on

          • Login

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