QtWidgets实现线条仅点击按住时随鼠标移动的方案求助
解决QtWidgets中Matplotlib竖线仅拖拽时跟随鼠标的问题
需求说明
当前已实现随鼠标自动移动的Matplotlib竖线,需要修改为仅在点击并按住竖线本身时才跟随鼠标移动,未按住鼠标左键时保持静止。
修改方案
核心思路是通过添加鼠标按下/释放事件监听,判断点击位置是否在竖线上,设置拖拽状态标志,仅在拖拽状态开启时响应鼠标移动事件更新竖线位置:
- 新增
self.dragging标志位,记录是否处于拖拽状态 - 监听
button_press_event,判断点击坐标是否命中竖线,命中则开启拖拽 - 监听
button_release_event,释放时关闭拖拽 - 修改
mouse_move方法,仅在self.dragging为True时更新竖线位置
修改后的完整代码
import numpy as np from PySide2 import QtWidgets from matplotlib.backends.backend_qt5agg import FigureCanvas from matplotlib.figure import Figure import matplotlib.pyplot as plt class SnaptoCursor(object): def __init__(self, ax, x): self.ax = ax self.ly = ax.axvline(color='k') self.x = x self.txt = ax.text(0.7, 0.9, '', transform=ax.transAxes) self.dragging = False # 新增拖拽状态标志 def mouse_press(self, event): # 仅处理左键点击,且点击位置在竖线上 if event.button == 1 and event.inaxes: # 获取竖线的x位置,判断鼠标x坐标是否接近竖线 line_x = self.ly.get_xdata()[0] # 允许一定误差范围,避免点击精度问题 if abs(event.xdata - line_x) < 0.5: self.dragging = True def mouse_release(self, event): if event.button == 1: self.dragging = False def mouse_move(self, event): # 仅在拖拽状态开启且鼠标在坐标轴内时更新 if self.dragging and event.inaxes: indx = np.searchsorted(self.x, [event.xdata])[0] x = self.x[indx] self.ly.set_xdata(x) self.txt.set_text('x=%1.2f' % x) self.ax.figure.canvas.draw() else: pass class App(QtWidgets.QMainWindow): def __init__(self, parent=None): super(App, self).__init__(parent) self._main = QtWidgets.QWidget() self.setCentralWidget(self._main) self.figure = Figure(figsize=(10, 6.9)) self.canvas = FigureCanvas(self.figure) self.canvas_ax = self.canvas.figure.subplots() x = np.arange(0,40) self.cursor = SnaptoCursor(self.canvas_ax, x) # 新增鼠标按下和释放事件的监听 self.canvas.mpl_connect('button_press_event', self.cursor.mouse_press) self.canvas.mpl_connect('button_release_event', self.cursor.mouse_release) self.canvas.mpl_connect('motion_notify_event', self.cursor.mouse_move) self.canvas_ax.plot(x, np.random.rand(40)) # Layout layout = QtWidgets.QVBoxLayout(self._main) layout.addWidget(self.canvas) self.showMaximized() if __name__ == '__main__': app = QtWidgets.QApplication([]) ex = App() ex.show() app.exec_()
代码说明
mouse_press方法:判断左键点击是否命中竖线(设置了0.5的误差范围,可根据需求调整),命中则开启拖拽状态mouse_release方法:释放左键时关闭拖拽状态mouse_move方法:仅在拖拽状态开启时,才更新竖线位置和显示文本
内容的提问来源于stack exchange,提问作者Josh.h
相关产品推荐
相关产品推荐

