首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何识别QGraphicsItem?

如何识别QGraphicsItem?
EN

Stack Overflow用户
提问于 2021-12-14 18:18:31
回答 1查看 314关注 0票数 0

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

更新以下是我的一些代码

代码语言:javascript
复制
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()

提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-15 16:42:50

QGraphicsItem不是QObject,所以它不支持属性系统,但是它对通过setData()存储属性的支持有限。

代码语言:javascript
复制
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)))

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

重要的是要考虑,虽然您可能尝试为addRect()返回的项设置一个属性,但这是行不通的:我们应该记住,PyQt是一个绑定到Qt的对象,所有用于Qt对象的python对象都是包装器。

请考虑以下几点:

代码语言:javascript
复制
    def creator(self):
        # ...
        rect.id = self.count

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

这将始终打印False,这是因为我们只在creator中为包装器引用创建了一个属性,但由于该引用只是本地引用,并且该属性是在该引用(而不是包装对象)上设置的,因此它将被垃圾收集,属性将丢失。

一种可能的办法是为每个项目添加一个持久的参考资料:

代码语言:javascript
复制
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包装器将是持久的,属性将被保留:

代码语言:javascript
复制
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))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70353754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档