如何识别 QGraphicsItem?

How to identify a QGraphicsItem?

我想知道是否有办法获取 QGraphicsItem 的 ID。没什么复杂的。假设我有一个 QGraphicsScene,我在其中创建了许多相同大小和颜色的矩形。即使没有 ID,我如何识别它们?

更新 这是我的一些代码

class Test(QtWidgets.QDialog):

    def __init__(self):
        super(Test, self).__init__()
        
        loader = QtUiTools.QUiLoader()
        self.ui = loader.load(ui_path, self)
        self.variables()
        
        self.ui.create_button.clicked.connect(self.creator)
        self.scene.focusItemChanged.connect(self.nameDisplay)
        
    def variables(self):        
        self.scene = QtWidgets.QGraphicsScene()
        self.ui.canvas_area.setScene(self.scene)
        
         
    def creator(self):
        rect = self.scene.addRect(-20,-20,40,40, QPen(Qt.red), QBrush(Qt.gray))
        rect.setFlag(QGraphicsItem.ItemIsMovable)
        rect.setFlag(QGraphicsItem.ItemIsFocusable)
        rect.setFlag(QGraphicsItem.ItemIsSelectable)
        
    def nameDisplay(self, newFocusItem, oldFocusItem, reason):
        self.ui.name_line.setText(str(self.scene.focusItem()))       
                
if __name__ == '__main__':
    test_window = Test()
    test_window.ui.show()

提前致谢!

QGraphicsItem 不是 QObject,因此它不支持 属性 系统,但它对通过 setData().

存储属性的支持有限
class Test(QtWidgets.QDialog):
    count = 0
    # ...

    def creator(self):
        rect = self.scene.addRect(-20,-20,40,40, QPen(Qt.red), QBrush(Qt.gray))
        rect.setFlag(QGraphicsItem.ItemIsMovable)
        rect.setFlag(QGraphicsItem.ItemIsFocusable)
        rect.setFlag(QGraphicsItem.ItemIsSelectable)
        rect.setData(0, self.count)
        self.count += 1

    def nameDisplay(self, newFocusItem, oldFocusItem, reason):
        if newFocusItem and newFocusItem.data(0) is not None:
            self.ui.name_line.setText('Item {}'.format(newFocusItem.data(0)))

注意:setData()data()key 参数必须是整数,并且无法知道是否设置了(以及设置了哪些)键:您只能检查如果键值不是 None。如果你需要更复杂的数据映射,你可以使用字典作为值,或者只是子类(见下文)。

重要的是要考虑到,虽然有人可能会尝试为 addRect() 返回的项目设置属性,但这是行不通的:我们应该记住 PyQt 是 Qt 的绑定,所有 python 用于 Qt 对象的对象是 wrappers.

考虑以下因素:

    def creator(self):
        # ...
        rect.id = self.count

    def nameDisplay(self, newFocusItem, oldFocusItem, reason):
        print(hasattr(newFocusItem, 'id')

这将始终打印 False,那是因为我们只在 creator 中为包装器引用创建了一个属性,但由于该引用只是本地的并且属性设置在 [=41] =]that reference (not wrapped object), 它将被垃圾收集并且属性将丢失。

一个可能的选择是为每个项目添加一个持久引用:

class Test(QtWidgets.QDialog):
    def __init__(self):
        # ...
        self.items = []

    def creator(self):
        # ...
        rect.id = self.count
        self.items.append(rect)

但我建议坚持使用 setData() 选项,因为它更符合 Qt 的工作方式。

或者,我们可以创建一个自定义的 QGraphicsRectItem 子类并使用 self.scene.addItem() 添加它。在这种情况下,python 包装器将持久存在并且属性将被保留:

class MyRect(QtWidgets.QGraphicsRectItem):
    def __init__(self, id, x, y, w, h, pen, brush):
        super().__init__(x, y, w, h)
        self.id = id
        self.setPen(pen)
        self.setBrush(brush)

class Test(QtWidgets.QDialog):
    # ...
    def creator(self):
        rect = MyRect(self.count, -20, -20, 40, 40, QPen(Qt.red), QBrush(Qt.gray))
        self.scene.addItem(rect)
        # ...

    def nameDisplay(self, newFocusItem, oldFocusItem, reason):
        if hasattr(newFocusItem, 'id'):
            self.name_line.setText('Item {}'.format(newFocusItem.id))