QGraphicsObject中mouseMove与mousePress事件鼠标位置不一致问题咨询
解决QGraphicsObject缩放后鼠标事件位置不一致的问题
嘿,这个缩放导致鼠标事件位置错位的问题我太熟悉了!咱们直接说结论:确实需要根据缩放更新boundingRect,而且还要配合正确的坐标转换和Qt的几何更新机制,具体操作如下:
核心原因
未缩放时,场景坐标和你的TicTacToe item的局部坐标是1:1映射的,所以mousePressEvent和mouseMoveEvent里的位置能对上;但缩放后,item的实际显示尺寸变了,如果boundingRect没同步更新,Qt会用旧的边界来判断事件是否属于这个item,再加上你如果直接用场景坐标而不转成item局部坐标,就会出现位置差异。
具体操作步骤
1. 维护缩放因子变量
在你的TicTacToe类里添加一个私有变量来记录当前缩放比例:
class TicTacToe(QGraphicsObject): def __init__(self, parent=None): super().__init__(parent) self._scale = 1.0 # 初始缩放因子为1.0 # 其他初始化代码...
2. 重写boundingRect()方法,基于缩放因子返回正确边界
确保boundingRect始终匹配item缩放后的实际尺寸:
def boundingRect(self): # 假设你原本的item基础尺寸是100x100,根据缩放因子调整 original_width = 100 original_height = 100 return QRectF(0, 0, original_width * self._scale, original_height * self._scale)
3. 执行缩放时更新因子并通知Qt几何变化
当你对item进行缩放操作时,一定要先调用prepareGeometryChange()(告诉Qt你的item几何形状要更新了),再修改缩放因子:
def set_scale(self, new_scale): self.prepareGeometryChange() # 必须先调用这个!否则Qt不会重新计算事件区域 self._scale = new_scale self.update() # 触发重绘,让缩放效果生效
4. 鼠标事件中转换为item局部坐标
在mousePressEvent和mouseMoveEvent里,把场景坐标转换为item自身的局部坐标,这样不管缩放多少,拿到的都是item坐标系下的位置:
def mousePressEvent(self, event): # 把场景坐标转成item局部坐标 local_pos = self.mapFromScene(event.pos()) print("鼠标点击局部位置:", local_pos) # 你的其他处理逻辑... super().mousePressEvent(event) def mouseMoveEvent(self, event): local_pos = self.mapFromScene(event.pos()) print("鼠标移动局部位置:", local_pos) # 你的其他处理逻辑... super().mouseMoveEvent(event)
完整修改后的代码片段
#!/usr/bin/env python from PyQt5.QtCore import QRectF from PyQt5.QtGui import QPainter, QPixmap from PyQt5.QtWidgets import QMainWindow, QApplication, QGraphicsObject, QGraphicsView, QGraphicsScene class TicTacToe(QGraphicsObject): def __init__(self, parent=None): super().__init__(parent) self._scale = 1.0 # 替换成你实际使用的资源或基础尺寸 self._base_width = 100 self._base_height = 100 self._pixmap = QPixmap("tic_tac_toe.png") # 可选:如果用图片绘制 def boundingRect(self): return QRectF(0, 0, self._base_width * self._scale, self._base_height * self._scale) def paint(self, painter, option, widget): painter.scale(self._scale, self._scale) if not self._pixmap.isNull(): painter.drawPixmap(0, 0, self._pixmap) else: # 无图片时绘制基础矩形 painter.drawRect(0, 0, self._base_width, self._base_height) def set_scale(self, new_scale): self.prepareGeometryChange() self._scale = new_scale self.update() def mousePressEvent(self, event): local_pos = self.mapFromScene(event.pos()) print(f"点击局部坐标:{local_pos.x()}, {local_pos.y()}") super().mousePressEvent(event) def mouseMoveEvent(self, event): local_pos = self.mapFromScene(event.pos()) print(f"移动局部坐标:{local_pos.x()}, {local_pos.y()}") super().mouseMoveEvent(event) # 测试用主窗口 class MainWindow(QMainWindow): def __init__(self): super().__init__() self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene) self.setCentralWidget(self.view) self.tic_tac_toe = TicTacToe() self.scene.addItem(self.tic_tac_toe) # 测试缩放:比如放大到1.5倍 self.tic_tac_toe.set_scale(1.5) if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() app.exec_()
这样操作后,不管你怎么缩放,鼠标事件的位置都会和item的实际显示区域匹配,不会再出现错位的问题啦~
内容的提问来源于stack exchange,提问作者Aquarius_Girl
相关产品推荐
相关产品推荐

