【问题标题】:Select items in QGraphicsScene using PySide?使用 PySide 在 QGraphicsScene 中选择项目?
【发布时间】:2017-10-30 03:01:06
【问题描述】:

我需要创建几个可移动、可选择的图形项目。一个项目保持选中状态,直到选择了不同的项目或用户单击场景的空白部分,取消选择所有项目。选定的项目必须与未选定的项目看起来不同。主窗口的任何小部件都应该能够查询是否选择了一个图形项以及——如果是——是哪一个。

此代码允许在屏幕上选择和移动项目。移动时项目变为红色:

import sys
from PySide import QtGui, QtCore

class MainWindowUi(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.scene = Scene(0, 0, 300, 300, self)
        self.view = QtGui.QGraphicsView()
        self.setCentralWidget(self.view)
        self.view.setScene(self.scene)
        self.scene.addItem(Line(25,25,25,50))
        self.scene.addItem(Line(30,30,30,70))
        self.scene.addItem(Line(35, 40, 35, 65))

class Scene(QtGui.QGraphicsScene):
    pass

class Line(QtGui.QGraphicsLineItem):
    def __init__(self, *args):
        QtGui.QGraphicsLineItem.__init__(self)
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        self.setPen(QtGui.QPen(QtCore.Qt.black, 3))

    def mousePressEvent(self, e):
        self.setPen(QtGui.QPen(QtCore.Qt.red, 5))
        QtGui.QGraphicsLineItem.mousePressEvent(self, e)

    def mouseReleaseEvent(self, e):
        self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
        QtGui.QGraphicsLineItem.mouseReleaseEvent(self, e)

if __name__ == '__main__':
    a = QtGui.QApplication(sys.argv)
    m = MainWindowUi()
    m.show()
    sys.exit(a.exec_())

这是我的问题:

  1. 在 Qt 中,图形项是在移动时被选中,在释放时被取消选中?

  2. 鼠标释放后如何保持选中图形项?例如,我应该在“Line”中创建一个名为 self.selected 的布尔变量吗?

  3. 应用程序如何查询选择了哪个图形项并区分它们?例如,是否应该为“Line”类中的每个项目分配一个唯一的 ID,还是 Qt 已经这样做了?

【问题讨论】:

    标签: python pyside qgraphicsscene


    【解决方案1】:

    在 Qt 中,是一个图形项,在移动时被选中,在移动时被取消选中 发布了吗?

    当一个项目被点击时,一个项目被选中,当你选择另一个项目或当你点击一个空白区域时取消选择。

    鼠标释放后图形项如何保持选中状态?为了 例如,我是否应该在“Line”中创建一个名为 自选?

    从上一个答案中,元素仍然被选中,此外已经有函数 selected() 返回 True 或 False 以及是否选择了该项目。

    应用程序如何查询选择了哪个图形项以及 区分它们?例如,应该类中的每个项目 “线”被分配了一个唯一的 ID 还是 Qt 已经这样做了?

    QGraphicsScene 具有返回所选项目的selectedItems() 方法。 Qt 不提供 ID 或类似的东西,要执行该任务,我们可以使用 setData()data() 方法,第一个通过密钥保存一些信息,另一个使用相同的密钥恢复它。

    要检测项目中的更改,您必须覆盖itemChange() 方法,这为我们提供了更改的类型和更改的值。在您的情况下,您应该验证更改必须是 ItemSelectedChange 类型,如果选中则为 True,如果未选中则为 False。

    def itemChange(self, change, value):
        if change == QtGui.QGraphicsItem.ItemSelectedChange:
            if value:
                self.setPen(QtGui.QPen(QtCore.Qt.red, 3))
            else:
                self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
        return QtGui.QGraphicsLineItem.itemChange(self, change, value)
    

    例子:

    class MainWindowUi(QtGui.QMainWindow):
        def __init__(self, *args, **kwargs):
            QtGui.QMainWindow.__init__(self, *args, **kwargs)
            self.scene = Scene(0, 0, 300, 300, self)
            self.view = QtGui.QGraphicsView(self)
            self.setCentralWidget(self.view)
            self.view.setScene(self.scene)
            self.scene.addItem(Line(25, 25, 25, 50))
            self.scene.addItem(Line(30, 30, 30, 70))
            self.scene.addItem(Line(35, 40, 35, 65))
            self.scene.selectionChanged.connect(self.onSelectionChanged)
    
        def onSelectionChanged(self):
            message = "Items selecteds: "
            for item in self.scene.selectedItems():
                message += " " + item.data(Scene.NameItem)
            self.statusBar().showMessage(message)
    
    
    class Scene(QtGui.QGraphicsScene):
        NameItem = 1
    
        def __init__(self, *args, **kwargs):
            QtGui.QGraphicsScene.__init__(self, *args, **kwargs)
            self.counterItems = 0
    
        def addItem(self, item):
            item.setData(Scene.NameItem, "item {}".format(self.counterItems))
            self.counterItems += 1
            QtGui.QGraphicsScene.addItem(self, item)
    
    
    class Line(QtGui.QGraphicsLineItem):
        def __init__(self, *args, **kwargs):
            QtGui.QGraphicsLineItem.__init__(self, *args, **kwargs)
            self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
            self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
            self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
    
        def itemChange(self, change, value):
            if change == QtGui.QGraphicsItem.ItemSelectedChange:
                if value:
                    self.setPen(QtGui.QPen(QtCore.Qt.red, 3))
                else:
                    self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
            return QtGui.QGraphicsLineItem.itemChange(self, change, value)
    

    【讨论】:

    • 谢谢。您对item.setData() 的演示也很有帮助。
    【解决方案2】:

    在 Qt 中,是一个图形项,在移动时被选中,在移动时被取消选中 发布了吗?

    不,默认情况下,qgraphics 项目会在鼠标单击时被选中,即使松开鼠标也会保持选中状态。

    鼠标释放后图形项如何保持选中状态?为了 例如,我是否应该在“Line”中创建一个名为 自选?

    一个qgraphics知道它是否被选中,你可以询问它查询它的isSelected()方法。

    应用程序如何查询选择了哪个图形项以及 区分它们?例如,应该类中的每个项目 “线”被分配了一个唯一的 ID 还是 Qt 已经这样做了?

    从应用程序的角度来看,它可以调用QGraphicsScene::selectedItems()方法获取所有选中的项目。

    您可能会阅读描述如何使用它的graphics api documentation

    【讨论】:

    • 没有区别:当我发帖时,我看到你回答了,而我正在写我的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多