我将项目添加到 GraphicsScene 中,该项目应以固定大小显示在屏幕上,与放大和缩小无关。 我通过以下方式创建它们:
class LocationGraphicsItem(QtWidgets.QGraphicsEllipseItem):
def __init__(self, coordinate, parent = None):
super().__init__(parent=parent)
x = coordinate[0]
y = -coordinate[1]
self.setRect(-5, -5, 10, 10)
self.setPos(x, y)
self.setFlag(self.GraphicsItemFlag.ItemIgnoresTransformations)
我将它们添加到场景中,如下所示:
coordinate = (3412770.9, 5358376.3)
item = LocationGraphicsItem(coordinate)
my_scene.addItem(item)
item.ensureVisible()
稍后致电
my_view.fitInView(my_scene.sceneRect(), Qt.KeepAspectRatio)
在我看来。 只要我在 Qt 事件循环启动之前添加所有这些,视图就会设置为显示正确的范围,场景就会计算出正确的
sceneRect
,类似于:
PySide6.QtCore.QRectF(3412765.400000, -5371895.600000, 82420.600000, 13524.800000)
但是,如果我在事件循环启动后添加项目并且
QGraphicsView
已经可见,则我的兴趣区域会被限制在右上角,因为 sceneRect
更改为:
PySide6.QtCore.QRectF(-5.500000, -5371895.600000, 3495191.500000, 5371901.100000)
如何避免这种情况?有人可以向我解释为什么会发生这种情况吗? 我知道我可以用
my_scene.itemsBoundingRect()
重新计算相关矩形,不幸的是这很慢。
实现固定大小标记的替代方案/最佳实践是什么?无论如何,我更愿意以像素为单位指定大小。
这是一些完整的代码:
import random
import sys
print("Python: ", sys.version)
import PySide6
print("PySide: ", PySide6.__version__)
from PySide6 import QtCore, QtGui, QtWidgets
class LocationGraphicsItem(QtWidgets.QGraphicsEllipseItem):
def __init__(self, coordinate, parent = None):
super().__init__(parent=parent)
x = coordinate[0]
y = -coordinate[1]
self.setRect(-5, -5, 10, 10)
self.setPos(x, y)
self.setBrush(QtGui.QColor("blue"))
self.setFlag(self.GraphicsItemFlag.ItemIgnoresTransformations)
def add_something():
print(scene.sceneRect())
point =(3.4e6+random.random()*1e5, 5.3e6+random.random()*1e5)
print("Random point: ", point)
item = LocationGraphicsItem(point)
scene.addItem(item)
item.setVisible(True)
item.ensureVisible()
view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
QtWidgets.QApplication.processEvents()
print(scene.sceneRect())
if __name__ == "__main__":
my_points = [(3412770.9, 5358376.3), (3495180.5, 5371890.1), (3495099.1, 5370624.6), (3485765.4, 5371030.1)]
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene()
for point in my_points:
item = LocationGraphicsItem(point)
scene.addItem(item)
item.setVisible(True)
item.ensureVisible()
window = QtWidgets.QMainWindow(parent = None)
window.setGeometry(50, 50, 1300, 750)
basic_widget = QtWidgets.QWidget(parent=window)
window.setCentralWidget(basic_widget)
layout = QtWidgets.QHBoxLayout()
basic_widget.setLayout(layout)
button = QtWidgets.QPushButton("add something", parent = basic_widget)
button.clicked.connect(add_something)
layout.addWidget(button)
view = QtWidgets.QGraphicsView(scene, parent = basic_widget)
layout.addWidget(view)
view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
window.setVisible(True)
app.exec()
输出:
Python: 3.11.0 (main, Oct 24 2022, 18:26:48) [MSC v.1933 64 bit (AMD64)]
PySide: 6.4.0.1
PySide6.QtCore.QRectF(3412765.400000, -5371895.600000, 82420.600000, 13524.800000)
Random point: (3449076.7327629146, 5323846.465410875)
PySide6.QtCore.QRectF(-5.500000, -5371895.600000, 3495191.500000, 5371901.100000)
这似乎是一个Qt bug。为什么不报告呢? (请参阅报告错误。)
您可以通过手动调用
QGraphicsItem.sceneTransform()
来修复它,如下所示。
def add_something():
...
item = LocationGraphicsItem(point)
scene.addItem(item)
...
dummy = item.sceneTransform()
view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
...