Qt QtGraphicsView Example

In this article we cover QtGraphicsView overriding the main class.

Qt QtGraphicsView Example

The Qt Framework is a powerful developmental platform and somewhat tricky to learn.

  • We will look at overriding the QGraphicsView example in this tutorial.
  • This is the example overload that initializes itself:
class Mfft_draw(QtWidgets.QGraphicsView):
    def __init__(self, parent):
        super(Mfft_draw, self).__init__(parent)

Next we overload the draw function:

    def draw(self, indata=None):
    	self.image = QImage(self.width, self.height, QImage.Format_RGB32)
        self.image.fill(QColor(220,220,220))
        qpainter = QPainter(self.image)
        qpainter.setBrush(QColor(255,255,255))
        qpainter.setPen(QColor(20,20,20))  
        qpainter.drawRect(x1, y1, box_size, box_size)
        qpainter.end()
        self.pixmap = QPixmap.fromImage(self.image)
        self.pixmapItem = QGraphicsPixmapItem(self.pixmap)
        scene = QGraphicsScene()
        scene.clear()
        scene.addItem(self.pixmapItem)
        self.setScene(scene)

A lot of moving parts but lets go over it:

1. self.image is created matching QImage (the parent) and dimensions match
2. qpainter is created 
3. qpainter.setBrush / setPen is created.
4. qpainter draws various rectangles / ellipses etc.
5. pixmap is created from self.image
6. pixmapItem is created from self.pixmap
7. scene is created from QGraphicsScene()
8. scene adds item (self.pixmapItem)
9. Finally self.setScene(scene)

Also it needs understanding that self.draw() is not automatically called!

Thus we can attach a call for it to the self.

QGraphicsView getting scene delta:

    def wheelEvent(self, event):
        # Override the wheel event to zoom in and out
        zoom_factor = 1.05
        if event.angleDelta().y() > 0:
            self.scale(zoom_factor, zoom_factor)
        else:
            self.scale(1 / zoom_factor, 1 / zoom_factor)
  • Scenes are like a sub-card inside the QImage / QGraphicsView Frame.
  • Relative scene coordinates can be referenced against the main QGraphicsView.
        scene_pos = self.mapToScene(event.pos())
        print(f"Mouse position in scene coordinates: {scene_pos.x()}, {scene_pos.y()}")
  • To set mouse tracking:
self.tab.setMouseTracking(True)

A full translation example:

  • Mouse will be able to pan / zoom the current scene with these sub-functions!
    def resizeEvent(self, event):
        self.width = event.size().width()
        self.height = event.size().height()
        self.draw()
    def wheelEvent(self, event):
        #region Reference Scene Scaling Example
        zoom_factor = 1.15
        if event.angleDelta().y() > 0:
            self.scale(zoom_factor, zoom_factor)
        else:
            self.scale(1 / zoom_factor, 1 / zoom_factor)
        #endregion
    def mousePressEvent(self, event):
        if  event.button() == Qt.LeftButton:
            self.startPos = event.pos()
            print(f"Setting self.startPos: {self.startPos}")
            self.click_mode = 'MOVE'
        else:
            self.startPos = None
        # Override the mouse press event for custom behavior
        epos = event.pos()
        scene_pos = self.mapToScene(event.pos())
        print(f"Mouse position in scene coordinates: {scene_pos.x()}, {scene_pos.y()}")
        super().mousePressEvent(event)
    def mouseMoveEvent(self, event):
        if self.startPos is not None:
            # compute the difference between the current cursor position and the
            # previous saved origin point
            delta = self.startPos - event.pos()
            # get the current transformation (which is a matrix that includes the
            # scaling ratios
            transform = self.transform()
            # m11 refers to the horizontal scale, m22 to the vertical scale;
            # divide the delta by their corresponding ratio
            deltaX = delta.x() / transform.m11()
            deltaY = delta.y() / transform.m22()
            # translate the current sceneRect by the delta
            self.setSceneRect(self.sceneRect().translated(deltaX, deltaY))
            # update the new origin point to the current position
            self.startPos = event.pos()
    def mouseReleaseEvent(self, event):
        self.startPos = None
Linux Rocks Every Day