解决QGraphicsView场景内双击鼠标时QGraphicsItem创建位置偏移问题
The core issue here is coordinate system mismatch: when you use event.pos() in the viewport's event filter, you're getting coordinates relative to the viewport widget itself, not the underlying QGraphicsScene. These two systems don't align if the view is zoomed, scrolled, or has any transformations applied.
How to Fix It
Use the mapToScene() method of your QGraphicsView (self.ui.canvas_area) to convert the viewport's mouse position into the scene's coordinate system. Here's the modified version of your createItems method:
def createItems(self, event): # Convert viewport coordinates to scene coordinates scene_position = self.ui.canvas_area.mapToScene(event.pos()) # Create the rectangle at the correct scene position rect = self.scene.addRect( scene_position.x(), scene_position.y(), 40, 40, QPen(Qt.red), QBrush(Qt.gray) ) rect.setFlag(QGraphicsItem.ItemIsMovable) rect.setFlag(QGraphicsItem.ItemIsFocusable) rect.setFlag(QGraphicsItem.ItemIsSelectable)
Why This Works
event.pos()gives you the mouse position within the viewport widget (pixels relative to the viewport's top-left corner).mapToScene()takes that viewport point and transforms it to the corresponding point in theQGraphicsScene's coordinate system, automatically accounting for any zoom, pan, or view transformations.
Bonus: Alternative Approach (Without Event Filter)
If you prefer a more straightforward setup, you could subclass QGraphicsView and override mouseDoubleClickEvent directly:
class CustomGraphicsView(QtWidgets.QGraphicsView): def __init__(self, scene, parent=None): super().__init__(scene, parent) def mouseDoubleClickEvent(self, event): scene_pos = self.mapToScene(event.pos()) rect = self.scene().addRect(scene_pos.x(), scene_pos.y(), 40, 40, QPen(Qt.red), QBrush(Qt.gray)) rect.setFlag(QGraphicsItem.ItemIsMovable) rect.setFlag(QGraphicsItem.ItemIsFocusable) rect.setFlag(QGraphicsItem.ItemIsSelectable) super().mouseDoubleClickEvent(event)
Then update your variables method to use this custom view:
def variables(self): self.scene = QtWidgets.QGraphicsScene() self.ui.canvas_area = CustomGraphicsView(self.scene, self.ui) # Reattach to your UI layout if necessary to ensure it displays correctly
Either method will resolve the position mismatch issue!
内容的提问来源于stack exchange,提问作者galaxy

