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.mouseMoveEvent
或 QGraphicsView.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。
我最近创建了一个程序,只要单击鼠标就会创建 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.mouseMoveEvent
或 QGraphicsView.mousePressEvent
。这些事件处理程序传递一个 QEvent
,其中包含相对于视图的鼠标坐标,因此在这些情况下,您不需要进行我在第一段中提到的全局坐标转换。
更新
我刚看到你的
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
注意:我已经根据