I see some people say if you want to put QGraphicsScene's origin of coordinates at the origin of QGraphicsView, i.e. top-left corner. You need to let both of them have the same size.
So here is what I do:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem,
QGraphicsScene, QGraphicsViewclass Demo(QGraphicsView):def __init__(self):super(Demo, self).__init__()self.resize(300, 300)self.line = QGraphicsLineItem()self.line.setLine(0, 0, 100, 100)self.scene = QGraphicsScene()self.scene.setSceneRect(0, 0, 300, 300)self.scene.addItem(self.line)self.setScene(self.scene)if __name__ == '__main__':app = QApplication(sys.argv)demo = Demo()demo.show()sys.exit(app.exec_())
The View's size is 300x300 and I use setSceneRect()
to make sure the Scene's size is 300x300.
In this case, the Scene's origin is at top-left corner.
However, when I use setSceneRect(0, 0, 150, 150)
, the origin is not there, but at (75, 75)!
Why? I thought the first two parameters of setSceneRect(x, y, w, h)
set where the origin of coordinates should be. When the Scene is smaller than View, how can we make sure the Scene's origin is at the top-left corner?
Any help would be appreciated!
As the docs point out:
alignment : Qt::Alignment
This property holds the alignment of the
scene in the view when the whole scene is visible.
If the whole scene is visible in the view, (i.e., there are no visible
scroll bars,) the view's alignment will decide where the scene will be
rendered in the view. For example, if the alignment is
Qt::AlignCenter, which is default, the scene will be centered in the
view, and if the alignment is (Qt::AlignLeft | Qt::AlignTop), the
scene will be rendered in the top-left corner of the view.
So, by default, the scenerect is centered with the viewport of the QGraphicsView, and in the case of having the same size, the behavior you point out is observed, but in the second case the property of the centering is highlighted.
So the solution is to establish the alignment to:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import Qtclass Demo(QGraphicsView):def __init__(self):super(Demo, self).__init__()self.resize(300, 300)self.line = QGraphicsLineItem()self.line.setLine(0, 0, 100, 100)self.scene = QGraphicsScene()self.scene.setSceneRect(0, 0, 150, 150)self.scene.addItem(self.line)self.setScene(self.scene)self.setAlignment(Qt.AlignTop | Qt.AlignLeft)if __name__ == '__main__':app = QApplication(sys.argv)demo = Demo()demo.show()sys.exit(app.exec_())
Explanation:
To understand what the scenerect is first, it must be understood that it is the QGraphicsView and the QGraphicsScene, these concepts are explained with an analogy to the recording of a movie, the QGraphicsView would be the camera, the QGraphicsScene represents what is recorded, ie the scene. The scene is delimited by the sceneRect, if the camera is very close to the scene, its limits will not be observed, but if the camera is far away, the scenerect projection in the camera will not occupy the whole screen, so it will have to be aligned in some position, in the case of QGraphicsView the alignment property is used.
why the scene is no longer centered in the view if I use setSceneRect(50, 50, 150, 150)?
To answer I use the following example where to make the scenerect visible I use a QGraphicsRectItem:
import sys
from PyQt5 import QtCore, QtGui, QtWidgetsclass Demo(QtWidgets.QGraphicsView):def __init__(self):super(Demo, self).__init__()self.resize(300, 300)self.line = QtWidgets.QGraphicsLineItem()self.line.setLine(0, 0, 100, 100)self.scene = QtWidgets.QGraphicsScene()self.scene.setSceneRect(50, 50, 150, 150)self.scene.addItem(self.line)rect_item = self.scene.addRect(QtCore.QRectF(50, 50, 150, 150))rect_item.setPen(QtGui.QPen(QtGui.QColor("green")))self.setScene(self.scene)if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)demo = Demo()demo.show()sys.exit(app.exec_())
As you can see the alignment is not about QRectF(0, 0, w, h) but the center of QRectF(x, y, w, h) which in this case is (100,100). So keep centered on sceneRect in the QGraphicsView.