如何从QGraphicsItem继承scenePos?矢量编辑器椭圆坐标错误修复咨询
Hey there! Let's work through your ellipse coordinate issue for your vector editor, and first confirm your approach is totally on the right track.
关于你的技术思路是否正确
Absolutely! Using QGraphicsEllipseItem is the perfect choice for basic ellipse drawing in Qt's graphics framework—it's designed explicitly for this use case, handling all the low-level rendering for you. If later you need to add custom interactions (like custom selection handles, property change signals, or complex state management), subclassing QGraphicsObject makes sense too. For now, stick with QGraphicsEllipseItem for simplicity, as it will cover all your core drawing needs.
常见的椭圆坐标错误原因及修复方案
Most coordinate issues with QGraphicsEllipseItem boil down to two key mistakes: misunderstanding the item's rectangle parameters, or messing up coordinate system conversions between the view and scene. Let's break this down with fixes:
1. 混淆椭圆外接矩形的参数含义
The QGraphicsEllipseItem constructor (and setRect() method) uses (x, y, width, height) where:
xandyare the top-left corner of the ellipse's bounding rectangle, not the center.widthandheightare the full width/height of the rectangle (not half-sizes).
This is the #1 mistake people make—if you're passing center coordinates directly here, your ellipse will be offset.
2. 未正确转换视图与场景坐标系
When using QGraphicsView, mouse events give you coordinates relative to the view widget, not the QGraphicsScene. If you skip converting these to scene coordinates, your ellipse will be misplaced (especially if the view is zoomed or scrolled).
修复示例代码
Here's a corrected implementation for drawing ellipses with mouse drags, fixing both issues:
from PyQt5.QtWidgets import QMainWindow, QGraphicsScene, QGraphicsView, QGraphicsEllipseItem from PyQt5.QtCore import Qt, QPointF class VectorEditorWindow(QMainWindow): def __init__(self): super().__init__() self.setup_ui() self.drawing_start = None self.current_ellipse = None def setup_ui(self): self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene, self) self.setCentralWidget(self.view) self.setWindowTitle("Simple Vector Editor") self.resize(800, 600) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: # Convert view coordinates to scene coordinates self.drawing_start = self.view.mapToScene(event.pos()) # Initialize empty ellipse (will update during drag) self.current_ellipse = QGraphicsEllipseItem() self.current_ellipse.setPen(Qt.blue) self.scene.addItem(self.current_ellipse) def mouseMoveEvent(self, event): if self.drawing_start and self.current_ellipse: current_pos = self.view.mapToScene(event.pos()) # Calculate correct bounding rectangle (top-left corner + size) rect_x = min(self.drawing_start.x(), current_pos.x()) rect_y = min(self.drawing_start.y(), current_pos.y()) rect_width = abs(current_pos.x() - self.drawing_start.x()) rect_height = abs(current_pos.y() - self.drawing_start.y()) # Apply the rectangle to the ellipse self.current_ellipse.setRect(rect_x, rect_y, rect_width, rect_height) def mouseReleaseEvent(self, event): self.drawing_start = None self.current_ellipse = None
如果要以中心为基准绘制椭圆
If you want to draw ellipses by dragging from the center (instead of top-left), adjust the rectangle calculation like this:
def mouseMoveEvent(self, event): if self.drawing_start and self.current_ellipse: current_pos = self.view.mapToScene(event.pos()) # Calculate half-width/height from center to drag point half_width = abs(current_pos.x() - self.drawing_start.x()) half_height = abs(current_pos.y() - self.drawing_start.y()) # Compute top-left corner of the bounding rectangle rect_x = self.drawing_start.x() - half_width rect_y = self.drawing_start.y() - half_height # Full width/height is double the half-size self.current_ellipse.setRect(rect_x, rect_y, half_width * 2, half_height * 2)
总结
Your initial approach is solid—QGraphicsEllipseItem is exactly what you need for basic ellipse rendering. The coordinate errors you're seeing are almost certainly from either misusing the bounding rectangle parameters or skipping coordinate system conversion. Try the code above, and you should see your ellipses appearing in the correct positions!
内容的提问来源于stack exchange,提问作者Zooma

