尝试添加固定大小项目时 QGraphicsScene 出现意外行为

问题描述 投票:0回答:1

我将项目添加到 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)
python qt qgraphicsscene pyside6 qgraphicsitem
1个回答
0
投票

这似乎是一个Qt bug。为什么不报告呢? (请参阅报告错误。)

您可以通过手动调用

QGraphicsItem.sceneTransform()
来修复它,如下所示。

def add_something():
    ...
    item = LocationGraphicsItem(point)
    scene.addItem(item)
    ...
    dummy = item.sceneTransform()
    view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
    ...
© www.soinside.com 2019 - 2024. All rights reserved.