在pyqtgraph ViewBox的keyPressEvent中获取鼠标位置的问题
自定义pg.ViewBox按键事件获取鼠标位置的优化与问题修复
一、无需十字线的鼠标位置获取方案
不用额外创建十字线元素,直接通过坐标转换就能拿到ViewBox数据坐标系下的鼠标位置:
- 用
QCursor.pos()获取全局鼠标坐标 - 调用ViewBox的
mapFromGlobal()将全局坐标转为控件局部坐标 - 再通过
mapSceneToView()把局部坐标转换成视图的data坐标(即鼠标对应的数据位置)
代码片段示例:
def keyPressEvent(self, event): # 全局坐标转ViewBox局部坐标 local_pos = self.mapFromGlobal(QCursor.pos()) # 局部坐标转视图数据坐标 view_pos = self.mapSceneToView(local_pos) print(f"鼠标对应数据位置:x={view_pos.x():.2f}, y={view_pos.y():.2f}") # 调用父类方法,保证事件正常传递 super().keyPressEvent(event)
二、代码异常的修复线索
首次按键无响应的解决
ViewBox默认不接收键盘焦点,需要手动开启并主动设置焦点:
- 在CustomViewBox的
__init__方法中添加self.setFocusPolicy(Qt.StrongFocus),开启键盘焦点接收 - 在主窗口初始化时,给ViewBox主动设置焦点:
self.plot_widget.getViewBox().setFocus()
二次按键报错+重复打印的解决
问题出在重写keyPressEvent时未调用父类方法,导致事件被拦截引发异常循环。修复时必须在事件处理逻辑末尾加上super().keyPressEvent(event),保证事件正常向上传递。
修复后的完整最小代码
import pyqtgraph as pg from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtCore import Qt class CustomViewBox(pg.ViewBox): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 开启焦点策略,让ViewBox能处理键盘事件 self.setFocusPolicy(Qt.StrongFocus) def keyPressEvent(self, event): # 获取鼠标对应的数据位置 local_pos = self.mapFromGlobal(QCursor.pos()) view_pos = self.mapSceneToView(local_pos) print(f"鼠标位置:({view_pos.x():.2f}, {view_pos.y():.2f})") # 必须调用父类方法,避免事件异常 super().keyPressEvent(event) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.plot_widget = pg.PlotWidget(viewBox=CustomViewBox()) self.setCentralWidget(self.plot_widget) # 主动让ViewBox获取焦点,首次按键就能响应 self.plot_widget.getViewBox().setFocus() if __name__ == "__main__": app = QApplication([]) win = MainWindow() win.show() app.exec_()
内容的提问来源于stack exchange,提问作者Jesse Rio
相关产品推荐
相关产品推荐

