You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:25:16