在鼠标双击位置创建一个QGraphicsItem

Create a QGraphicsItem at the mouse double-click position

我正在编写一个程序,当双击发生时(在场景区域内)应该创建一个 QGraphicsItem,并且该项目必须在双击位置创建。我已经写了一些代码,但它不能正常工作。当我双击场景时,一个项目被创建,但在一个完全不同的地方。所以现在这就是问题所在。我需要在鼠标位置创建它。

这是我的代码:

ui_path = "C:/Users/User/Desktop/programming/Creator/Creator.ui"
        
class Creator(QtWidgets.QWidget):
    count = 0
    
    def __init__(self):
        super(Creator, self).__init__()

        loader = QtUiTools.QUiLoader()
        self.ui = loader.load(ui_path, self)
        
        self.variables()

        self.ui.canvas_area.viewport().installEventFilter(self) #canvas_area is the QGraphicsView

        self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint)

    def variables(self):
        self.scene = QtWidgets.QGraphicsScene()
        self.ui.canvas_area.setScene(self.scene)

    def eventFilter(self, obj, event):
        if obj is self.ui.canvas_area.viewport():
            if event.type() == QtCore.QEvent.MouseButtonDblClick:
                self.createItems(event)
        return super(Creator, self).eventFilter(obj, event)

    def createItems(self, event):
        pos = event.pos()
        self._x = pos.x()
        self._y = pos.y()

        rect = self.scene.addRect(self._x, self._y, 40, 40, QPen(Qt.red), QBrush(Qt.gray))
        
        rect.setFlag(QGraphicsItem.ItemIsMovable)
        rect.setFlag(QGraphicsItem.ItemIsFocusable)
        rect.setFlag(QGraphicsItem.ItemIsSelectable)


if __name__ == '__main__':
    creator_window = Creator()
    creator_window.ui.show()

我已经阅读了一些有关 mapFromScene 和 mapToScene 的内容,它们可以解决问题 - 但我不太了解如何使用它们。也有一些这样的例子,但我发现的都是用 C++ 编写的,我对此一无所知。因此,如果有人可以帮助我弄清楚如何解决这个问题,我将不胜感激。

您首先必须为场景设置场景矩形:

self.scene.setSceneRect(0, 0, 1000, 1000)

然后你必须将事件位置转换为场景坐标,像这样:

pos = self.canvas_area.mapToScene(event.pos())

这应该是修复您的示例所需的全部内容。


另一种可能值得考虑的方法是在场景中安装事件过滤器:

self.scene.installEventFilter(self)

然后过滤更专业的 graphics events:

def eventFilter(self, obj, event):
    if obj is self.scene:
        if event.type() == QtCore.QEvent.GraphicsSceneMouseDoubleClick:
            self.createItems(event)
    return super(Creator, self).eventFilter(obj, event)

这会创建一个 QGraphicsSceneMouseEvent, which has several useful features that a standard QMouseEvent doesn't have. This includes scenePos(),这样就不必一直映射到场景坐标,这样您就可以简单地执行以下操作:

pos = event.scenePos()