Qgraphicsview 项目未放置在应有的位置

Qgraphicsview items not being placed where they should be

我最近创建了一个程序,只要单击鼠标就会创建 QgraphicsEllipseItems。那部分有效!但是,它不在我光标所在的确切位置。它似乎比我的鼠标光标所在的位置略高。我确实创建了一个 QGraphicsRectItem,所以也许这两个项目相互冲突并相互远离?如何将这些圆圈放置在矩形项目的顶部?这是代码

class MyView(QtGui.QGraphicsView):
    def __init__(self):
        QtGui.QGraphicsView.__init__(self)

        self.scene = QtGui.QGraphicsScene(self)
        self.item = QtGui.QGraphicsRectItem(400, 400, 400, 400)
        self.scene.addItem(self.item)
        self.setScene(self.scene)
    def paintMarkers(self):
        self.cursor = QtGui.QCursor()
        self.x = self.cursor.pos().x()
        self.y = self.cursor.pos().y()
        self.circleItem = QtGui.QGraphicsEllipseItem(self.x,self.y,10,10)
        self.scene.addItem(self.circleItem)
        self.circleItem.setPen(QtGui.QPen(QtCore.Qt.red, 1.5))
        self.setScene(self.scene)

class Window(QtGui.QMainWindow):
    def __init__(self):
        #This initializes the main window or form
        super(Window,self).__init__()
        self.setGeometry(50,50,1000,1000)
        self.setWindowTitle("Pre-Alignment system")

        self.view = MyView()
        self.setCentralWidget(self.view)
    def mousePressEvent(self,QMouseEvent):
        self.view.paintMarkers()

非常感谢!

您用来放置 QGraphics...Item 的坐标有两个问题。第一个是 QCursor 的坐标是 global screen coordinates, so you need to use self.mapFromGlobal() 以将它们转换为相对于 QGraphicsView.

的坐标

其次,您实际上需要相对于当前 QGraphicsScene 的坐标,因为这是您绘制项目的位置。这是因为场景可以从视图偏移(例如,在比视图大的场景周围平移)。为此,您在相对于 QGraphicsView.

的坐标上使用 self.mapToScene()

我要指出的是,通常您会在 QGraphicsScene 上绘制一些内容以响应 QGraphicsView 中的某种鼠标事件,这需要重新实现 QGraphicsView.mouseMoveEventQGraphicsView.mousePressEvent。这些事件处理程序传递一个 QEvent,其中包含相对于视图的鼠标坐标,因此在这些情况下,您不需要进行我在第一段中提到的全局坐标转换。


更新

我刚看到你的 问题,现在对问题的某些部分有了更好的理解。您不应该覆盖主 window 中的鼠标事件。而是在视图中覆盖它。例如:

class MyView(QtGui.QGraphicsView):
    def __init__(self):
        QtGui.QGraphicsView.__init__(self)

        self.scene = QtGui.QGraphicsScene(self)
        self.item = QtGui.QGraphicsRectItem(400, 400, 400, 400)
        self.scene.addItem(self.item)
        self.setScene(self.scene)
    def paintMarkers(self, event):
        # event position is in coordinates relative to the view
        # so convert them to scene coordinates
        p = self.mapToScene(event.x(), event.y())
        self.circleItem = QtGui.QGraphicsEllipseItem(0,0,10,10)
        self.circleItem.setPos(p.x()-self.circleItem.boundingRect().width()/2.0, 
                               p.y()-self.circleItem.boundingRect().height()/2.0)
        self.scene.addItem(self.circleItem)
        self.circleItem.setPen(QtGui.QPen(QtCore.Qt.red, 1.5))
        # self.setScene(self.scene) # <-- this line should not be needed here

    # Note, I've renamed the second argument `event`. Otherwise you locally override the QMouseEvent class
    def mousePressEvent(self, event):
        self.paintMarkers(event)
        # you may want to preserve the default mouse press behaviour,
        # in which case call the following
        return QGraphicsView.mousePressEvent(self, event)

这里我们不需要使用 QWidget.mapFromGlobal()(我在第一段中提到的),因为我们使用 QGraphicsView 中的鼠标事件,returns 坐标相对于该小部件只有。


更新 2

注意:我已经根据 答案更新了上面代码中的项目 created/placed。