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. [PySide6] GraphicsView not showing - I'm evidently doing it wrong!

[PySide6] GraphicsView not showing - I'm evidently doing it wrong!

Scheduled Pinned Locked Moved Solved Qt for Python
pyside6qgraphicsviewlayoutbackground
8 Posts 2 Posters 1.8k 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.
  • J Offline
    J Offline
    jim87
    wrote on last edited by jim87
    #1

    Hello!

    I'm trying to set a QGraphicsView's background using a SVG image. I've thus extended it overwriting the drawBackground method (see PoC at the bottom).

    I currently create a scene, add a "stupid" rectangle, create a GraphicsView using the scene in the constructor and add the view to the layout of the application. The result is the following:

    6c511357-acef-4ae0-9566-19f151766ba9-immagine.png

    Which is... not what I wanted :D (I'd expect a window with a GraphicsScene with at least a rectangle with a custom view's background). What am I doing wrong?

    I've prepared a one-file PoC you can copy and try out.

    In the PoC I've created a click event listener to print out what's being clicked, and when you click on the darker area, it says "QObject" (because there is no object name, see code). I'd expect the MyGraphicsView to be logged.

    Thanks :)

    import sys
    from typing import Union
    from PySide6 import QtCore, QtGui
    from PySide6.QtSvg import QSvgRenderer
    from PySide6.QtWidgets import QApplication, QGraphicsScene, QGraphicsView, QMainWindow, QVBoxLayout, QWidget
    
    
    class MyGraphicsView(QGraphicsView):
        def drawBackground(self, painter: QtGui.QPainter, rect: Union[QtCore.QRectF, QtCore.QRect]) -> None:
            svg_data = '''
    <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
        <rect width="100%" height="100%" fill="#434343" fill-opacity="1" />
        <g fill-rule="evenodd">
            <g fill="#979797" fill-opacity="1">
                <path opacity=".5" d="M96 95h4v1h-4v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9zm-1 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9z" />
                <path d="M6 5V0H5v5H0v1h5v94h1V6h94V5H6z" />
            </g>
        </g>
    </svg>
            '''.encode('utf8')
    
            renderer = QSvgRenderer(contents=svg_data, parent=self)
    
            renderer.render(painter, rect)
    
    
    class WhatsUnderMouse(QtCore.QObject):
        def eventFilter(self, watched: QtCore.QObject, event: QtCore.QEvent) -> bool:
            if event.type() == QtCore.QEvent.MouseButtonPress:
                click_name = watched.objectName().strip() or type(watched)
                print(f'Clicked: {click_name}')
    
            return super().eventFilter(watched, event)
    
    
    if __name__ == '__main__':
        app = QApplication()
        app.setObjectName('The application')
        mouseEventFilter = WhatsUnderMouse()
        app.installEventFilter(mouseEventFilter)
    
        main = QMainWindow()
        main.setObjectName('Main window')
    
        central_widget = QWidget()
        layout = QVBoxLayout()
        central_widget.setLayout(layout)
        main.setCentralWidget(central_widget)
    
        rect = QtCore.QRect()
        rect.setWidth(400)
        rect.setHeight(400)
        main.setGeometry(rect)
    
        scene = QGraphicsScene()
        scene.setObjectName('The scene')
        rect = QtCore.QRectF(10, 10, 100, 100)
        scene.addRect(rect)
        view = MyGraphicsView(main)
        view.setObjectName('The graphics view')
        layout.addWidget(view)
    
        main.show()
    
        sys.exit(app.exec())
    
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #6

      You could make a brush out of your SVG image.

      See QGraphicsView::backgroundBrush property

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        I don't have a machine a hand so here are some suggestions:

        • Nuke all QMainWindow related code, you don't need it. Just show the graphics view.
        • You should check that your renderer is valid. You might be drawing a black rectangle on a black background.

        Once you have ensured that the renderer is valid and if you are still getting a black background, you can just call the base class implementation of drawBackground to check that it is working properly.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • J Offline
          J Offline
          jim87
          wrote on last edited by
          #3

          Hello @SGaist ,

          thanks for replying :)

          I've simplified as much as possible down to this:

          import sys
          from PySide6 import QtCore
          from PySide6.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
          
          if __name__ == '__main__':
              app = QApplication()
          
              scene = QGraphicsScene()
              rect = QtCore.QRectF(10, 10, 100, 100)
              scene.addRect(rect)
              view = QGraphicsView()
          
              view.show()
          
              sys.exit(app.exec())
          
          

          The resulting view is still empty:
          7a8ffeb2-8336-45bf-951d-ba0460dc38de-immagine.png

          So, supposing that the default renderer works as expected, I'm evidently missing something else :(

          Thank you very much for the support :)

          1 Reply Last reply
          0
          • J Offline
            J Offline
            jim87
            wrote on last edited by
            #4

            Ok, got some hints reading the code again:

            import sys
            from typing import Union
            from PySide6 import QtCore, QtGui
            from PySide6.QtSvg import QSvgRenderer
            from PySide6.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
            
            
            class MyGraphicsView(QGraphicsView):
                svg_renderer: QSvgRenderer
            
                def __init__(self, *args, **kwargs):
                    super().__init__(*args, **kwargs)
            
                    svg_data = '''
            <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
                <rect width="100%" height="100%" fill="#434343" fill-opacity="1" />
                <g fill-rule="evenodd">
                    <g fill="#979797" fill-opacity="1">
                        <path opacity=".5" d="M96 95h4v1h-4v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9zm-1 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9z" />
                        <path d="M6 5V0H5v5H0v1h5v94h1V6h94V5H6z" />
                    </g>
                </g>
            </svg>
                    '''.encode('utf8')
                    background_content = QtCore.QByteArray(svg_data)
                    self.svg_renderer = QSvgRenderer(background_content)
                    self.svg_renderer.setAspectRatioMode(
                        QtCore.Qt.AspectRatioMode.KeepAspectRatio)
            
                def drawBackground(self, painter: QtGui.QPainter, rect: Union[QtCore.QRectF, QtCore.QRect]) -> None:
            
                    self.svg_renderer.render(painter, rect)
            
            
            class WhatsUnderMouse(QtCore.QObject):
                def eventFilter(self, watched: QtCore.QObject, event: QtCore.QEvent) -> bool:
                    if event.type() == QtCore.QEvent.MouseButtonPress:
                        click_name = watched.objectName().strip() or type(watched)
                        print(f'Clicked: {click_name}')
            
                    return super().eventFilter(watched, event)
            
            
            if __name__ == '__main__':
                app = QApplication()
                app.setObjectName('The application')
                mouseEventFilter = WhatsUnderMouse()
                app.installEventFilter(mouseEventFilter)
            
                scene = QGraphicsScene()
                scene.setObjectName('The scene')
                pen = QtGui.QPen(QtGui.Qt.GlobalColor.yellow)
                brush = QtGui.QBrush(QtGui.Qt.GlobalColor.red)
                scene.addRect(10, 10, 100, 100, pen, brush)
                view = MyGraphicsView(scene)
                view.setObjectName('The graphics view')
            
                view.show()
            
                sys.exit(app.exec())
            
            

            Now it "works" just fine. The only thing missing now is that the drawBackground won't repeat the SVG pattern, but will render it once only, enlarging the graphic to match the size of the graphic view.

            1 Reply Last reply
            0
            • J Offline
              J Offline
              jim87
              wrote on last edited by jim87
              #5

              Ok, kind of got it working.

              This is the SVG background graphic view:

              class MyGraphicsView(QGraphicsView):
                  svg_renderer: QSvgRenderer
              
                  def __init__(self, *args, **kwargs):
                      super().__init__(*args, **kwargs)
              
                      svg_data = '''
              <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
                  <rect width="100%" height="100%" fill="#434343" fill-opacity="1" />
                  <g fill-rule="evenodd">
                      <g fill="#979797" fill-opacity="1">
                          <path opacity=".5" d="M96 95h4v1h-4v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9zm-1 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9z" />
                          <path d="M6 5V0H5v5H0v1h5v94h1V6h94V5H6z" />
                      </g>
                  </g>
              </svg>
                      '''.encode('utf8')
                      background_content = QtCore.QByteArray(svg_data)
                      self.svg_renderer = QSvgRenderer(background_content)
                      self.svg_renderer.setAspectRatioMode(
                          QtCore.Qt.AspectRatioMode.KeepAspectRatio)
              
                  def drawBackground(self, painter: QtGui.QPainter, rect: Union[QtCore.QRectF, QtCore.QRect]) -> None:
                      pattern_size = self.svg_renderer.defaultSize()
                      p_width = pattern_size.width()
                      p_height = pattern_size.height()
              
                      left_steps = math.ceil(rect.width() / pattern_size.width())
                      top_steps = math.ceil(rect.height() / pattern_size.height())
              
                      for w in range(0, left_steps):
                          for h in range(0, top_steps):
                              # print(w, h)
                              left = w * p_width
                              top = h * p_height
              
                              # print(top, left)
              
                              rect = QtCore.QRect()
                              rect.setTop(top)
                              rect.setLeft(left)
                              rect.setWidth(p_width)
                              rect.setHeight(p_height)
              
                              self.svg_renderer.render(painter, rect)
              
                      self.svg_renderer.render(painter, rect)
              
              

              Last step: it seems that the scene is centered, though all the surface seems to be the QGraphicsView (clicking on the surface with the click event handler):

              ec079d3d-b869-4de4-bf9c-8ee7ccd185d0-immagine.png

              Any hint on how to let the renderer paint on all the surface, and not only from the center downwards?

              EDIT: I kinda sorted it out, but I'm unsure whether it's the correct solution (due to the cyclic complexity). This is the drawBackground overwritten method:

                  def drawBackground(self, painter: QtGui.QPainter, rect: Union[QtCore.QRectF, QtCore.QRect]) -> None:
                          pattern_size = self.svg_renderer.defaultSize()
                          p_width = pattern_size.width()
                          p_height = pattern_size.height()
                  
                          left_steps = math.ceil(rect.width() / pattern_size.width())
                          top_steps = math.ceil(rect.height() / pattern_size.height())
                  
                          for w in range(0, left_steps):
                              for h in range(0, top_steps):
                                  left = w * p_width
                                  top = h * p_height
                                  for top_multiplier in [1, -1]:
                                      for left_multiplier in [1, -1]:
                                          rect = QtCore.QRect()
                                          rect.setTop(top_multiplier * top)
                                          rect.setLeft(left_multiplier * left)
                                          rect.setWidth(p_width)
                                          rect.setHeight(p_height)
                  
                                          self.svg_renderer.render(painter, rect)
              
              
              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #6

                You could make a brush out of your SVG image.

                See QGraphicsView::backgroundBrush property

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1
                • J Offline
                  J Offline
                  jim87
                  wrote on last edited by jim87
                  #7

                  Thanks @SGaist for the hint :) I made a way better solution for what I want to achieve. The code follows for future reference :)

                  class BlueprintGraphicsView(QGraphicsView):
                      def __init__(self, *args, **kwargs):
                          super().__init__(*args, **kwargs)
                  
                          svg_data = Path(__file__).parent.joinpath(
                              'images', 'background', 'graph-paper.svg').read_bytes()
                          background_content = QtCore.QByteArray(svg_data)
                          svg_renderer = QSvgRenderer(background_content)
                          svg_renderer.setAspectRatioMode(
                              QtCore.Qt.AspectRatioMode.KeepAspectRatio)
                  
                          brush_pixmap = QtGui.QPixmap(svg_renderer.defaultSize())
                  
                          brush_painter = QtGui.QPainter(brush_pixmap)
                          svg_renderer.render(brush_painter, brush_pixmap.rect())
                          brush_painter.end()
                  
                          self.setBackgroundBrush(QtGui.QBrush(brush_pixmap))
                  
                  
                  1 Reply Last reply
                  1
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    Great !

                    Since you have it working now, please mark the thread as solved using the "Topic Tools" button or the three dotted menu beside the answer you deem correct so that other forum users may know a solution has been found :-)

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    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