PyQt5:我无法理解 QGraphicsScene 的 setSceneRect(x, y, w, h)
PyQt5: I can't understand QGraphicsScene's setSceneRect(x, y, w, h)
我看有人说如果要把QGraphicsScene的坐标原点放在QGraphicsView的原点,即top-left角。你需要让它们的大小相同。
所以我是这样做的:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem,
QGraphicsScene, QGraphicsView
class 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_())
视图的大小为 300x300,我使用 setSceneRect()
确保场景的大小为 300x300。
在这种情况下,场景的原点位于 top-left 角。
然而,当我使用setSceneRect(0, 0, 150, 150)
时,原点不在那里,而是在(75, 75)!
为什么?我认为 setSceneRect(x, y, w, h)
的前两个参数设置坐标原点的位置。当Scene小于View时,如何保证Scene的原点在top-left角?
如有任何帮助,我们将不胜感激!
正如 docs 指出的那样:
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.
因此,默认情况下,scenerect 以 QGraphicsView 的视口为中心,在具有相同大小的情况下,会观察到您指出的行为,但在第二种情况下 属性居中的突出显示。
所以解决方案是建立对齐方式:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import Qt
class 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_())
解释:
首先要明白scenerect是什么,首先要明白就是QGraphicsView和QGraphicsScene,这些概念用类比电影的录制来解释,QGraphicsView就是相机,QGraphicsScene代表记录了什么,即场景。场景由 sceneRect 界定,如果相机离场景很近,则不会观察到它的限制,但如果相机很远,相机中的 scenerect 投影不会占据整个屏幕,所以它会有要在某个位置对齐,在 QGraphicsView 的情况下,使用对齐 属性。
如果我使用 setSceneRect(50, 50, 150, 150) 为什么场景不再居中?
为了回答我使用下面的示例,我使用 QGraphicsRectItem 使 scenerect 可见:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class 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_())
如您所见,对齐不是关于 QRectF(0, 0, w, h),而是关于 QRectF(x, y, w, h) 的中心,在本例中是 (100,100)。因此,请在 QGraphicsView 中以 sceneRect 为中心。
我看有人说如果要把QGraphicsScene的坐标原点放在QGraphicsView的原点,即top-left角。你需要让它们的大小相同。
所以我是这样做的:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem,
QGraphicsScene, QGraphicsView
class 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_())
视图的大小为 300x300,我使用 setSceneRect()
确保场景的大小为 300x300。
在这种情况下,场景的原点位于 top-left 角。
然而,当我使用setSceneRect(0, 0, 150, 150)
时,原点不在那里,而是在(75, 75)!
为什么?我认为 setSceneRect(x, y, w, h)
的前两个参数设置坐标原点的位置。当Scene小于View时,如何保证Scene的原点在top-left角?
如有任何帮助,我们将不胜感激!
正如 docs 指出的那样:
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.
因此,默认情况下,scenerect 以 QGraphicsView 的视口为中心,在具有相同大小的情况下,会观察到您指出的行为,但在第二种情况下 属性居中的突出显示。
所以解决方案是建立对齐方式:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import Qt
class 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_())
解释:
首先要明白scenerect是什么,首先要明白就是QGraphicsView和QGraphicsScene,这些概念用类比电影的录制来解释,QGraphicsView就是相机,QGraphicsScene代表记录了什么,即场景。场景由 sceneRect 界定,如果相机离场景很近,则不会观察到它的限制,但如果相机很远,相机中的 scenerect 投影不会占据整个屏幕,所以它会有要在某个位置对齐,在 QGraphicsView 的情况下,使用对齐 属性。
如果我使用 setSceneRect(50, 50, 150, 150) 为什么场景不再居中?
为了回答我使用下面的示例,我使用 QGraphicsRectItem 使 scenerect 可见:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class 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_())
如您所见,对齐不是关于 QRectF(0, 0, w, h),而是关于 QRectF(x, y, w, h) 的中心,在本例中是 (100,100)。因此,请在 QGraphicsView 中以 sceneRect 为中心。