如何让QGraphicsScene中拖动后的QGraphicsEllipseItem更新boundingRect?
解决QGraphicsEllipseItem拖动后位置未更新的问题
问题根源
你当前使用的boundingRect()返回的是图形项自身本地坐标系的矩形,拖动操作改变的是图形项在场景中的pos()(位置坐标),并不会修改它自身的boundingRect(),所以始终拿到初始值。要获取图形项在场景中的实际区域,需要用sceneBoundingRect()方法。
另外,你只在绘制完成(鼠标释放)时发送了一次roi_signal,拖动过程或拖动结束后没有触发信号更新,所以update_roi不会自动刷新位置。
具体解决步骤
1. 修正位置获取方式
修改Ui_MainWindow中的update_roi方法,把boundingRect()换成sceneBoundingRect():
def update_roi(self, roi): self.roi_atual = roi # 改用sceneBoundingRect获取场景中的实际区域 bounding_rect = self.roi_atual.sceneBoundingRect() print('new position', bounding_rect)
2. 监听图形项的位置变化
要在拖动时实时更新位置,需要监听图形项的位置变化事件,每次位置改变时重新发送roi_signal。可以通过自定义图形项类并重写itemChange方法实现:
首先定义继承自QGraphicsEllipseItem的自定义类:
class MovableEllipse(QtWidgets.QGraphicsEllipseItem): pos_changed = QtCore.pyqtSignal() def itemChange(self, change, value): # 当位置发生实际变化时发送信号 if change == QtWidgets.QGraphicsItem.GraphicsItemChange.ItemPositionHasChanged: self.pos_changed.emit() return super().itemChange(change, value)
然后在circleScene的mousePressEvent中替换原有的QGraphicsEllipseItem为自定义类,并连接信号:
def mousePressEvent(self, event): if not self.roi_closed: # 使用自定义的可拖动椭圆类 self.circle = MovableEllipse() self.circle.setPen(QPen(Qt.GlobalColor.black, 5, Qt.PenStyle.SolidLine)) self.circle.setBrush(QBrush(Qt.GlobalColor.blue, Qt.BrushStyle.FDiagPattern)) self.circle.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True) self.circle.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges, True) self.circle.setZValue(3) self.addItem(self.circle) # 连接位置变化信号到场景的roi_signal self.circle.pos_changed.connect(lambda: self.roi_signal.emit(self.circle)) self._start = event.scenePos() r = QtCore.QRectF(self._start, self._start) self.circle.setRect(r) super(circleScene, self).mousePressEvent(event)
这样每次拖动圆形时,只要位置发生变化,就会触发roi_signal,update_roi就能拿到最新的场景区域坐标。
内容的提问来源于stack exchange,提问作者Pedro D. Souza
相关产品推荐
相关产品推荐

