月下梧桐~ 2023-02-19 14:05 采纳率: 81.8%
浏览 56
已结题

在PYQT5界面的matplotlib子图中实现十字光标

如题,想实现贯穿每个子图的十字光标,试了很多次都没成功,求指点


import pandas as pd
import matplotlib
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
 
 
# 1配置QT界面
class ScrollableWindow(QtWidgets.QMainWindow):
    def __init__(self, fig):
        self.qapp = QtWidgets.QApplication([])  #QApplication类用于管理GUI应用程序的控制流和主要设置
        QtWidgets.QMainWindow.__init__(self)    #创建窗口
        self.widget = QtWidgets.QWidget()       #QtWidgets类提供用于UI的图形元素
        self.setCentralWidget(self.widget)      #将把widget设置为主窗口的中心窗口部件
        self.widget.setLayout(QtWidgets.QVBoxLayout())  #setLayout设置用户界面上的屏幕组件的格式布局
        self.widget.layout().setContentsMargins(0, 0, 0, 0) #设置左、上、右、下的外边距
        self.widget.layout().setSpacing(0)                  #设置各部件的相邻距离
        self.fig = fig                                      #fig 大画板
        self.canvas = FigureCanvas(self.fig)                #FigureCanvas画布
        self.canvas.draw()                                  #绘制
        self.scroll = QtWidgets.QScrollArea(self.widget)    #有滚动条的窗口
        self.scroll.setWidget(self.canvas)                  #创建滚动条
        self.nav = NavigationToolbar(self.canvas, self.widget)  #导航工具栏配置
        self.widget.layout().addWidget(self.nav)            #导航工具栏添加至窗口部件中
        self.widget.layout().addWidget(self.scroll)         #有滚动条的窗口添加至窗口部件中
        self.setWindowTitle('Test')
        self.show()
        exit(self.qapp.exec_())
 
# 2准备数据
data=\
[[816,420,20,-2.2],
 [817,440,19,-2.1],
 [818,430,22,-2.6],
 [819,470,27,-2.0],
 [819,510,24,-1.9],
 [820,410,30,-2.9]]
df=pd.DataFrame(data=data,columns=['深度','参数1','参数2','参数3'])
print(df)
 
# 3绘图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(20, 8)) #将父页面分割成3*1子界面,fig-大画板,axes-相当于图表
fig.suptitle('总标题', fontsize=14, fontweight='bold')
axes.flatten()[0].set_title('子图1', fontsize=12)
axes.flatten()[1].set_title('子图2', fontsize=12)
axes.flatten()[2].set_title('子图3', fontsize=12)
fig.subplots_adjust(left=0.05, right=0.95, bottom=0.1, top=0.9, wspace=0.2, hspace=0.4)
 
# 3.1绘制参数1曲线
x = df['深度'].tolist()
y = df['参数1'].tolist()
axes.flatten()[0].plot(x, y, label='参数1', linewidth=1)
axes.flatten()[0].set_ylim(400, 800)
 
# 3.1绘制参数2曲线
x = df['深度'].tolist()
y = df['参数2'].tolist()
axes.flatten()[1].plot(x, y, label='参数2', linewidth=1)
 
# 3.1绘制参数3曲线
x = df['深度'].tolist()
y = df['参数3'].tolist()
axes.flatten()[2].plot(x, y, label='参数3', linewidth=1)
 
ScrollableWindow(fig)
 
  • 写回答

3条回答 默认 最新

  • 不咕鸟会咕咕 2023-02-19 18:30
    关注

    可以使用matplotlib中的Cursor类来实现十字光标的显示。首先,在代码中导入Cursor类:

    from matplotlib.widgets import Cursor

    然后,在绘制子图时,创建Cursor对象,并将其添加到子图中即可:

    # 3.1绘制参数1曲线
    x = df['深度'].tolist()
    y = df['参数1'].tolist()
    axes.flatten()[0].plot(x, y, label='参数1', linewidth=1)
    axes.flatten()[0].set_ylim(400, 800)
    cursor1 = Cursor(axes.flatten()[0], useblit=True, color='red', linewidth=1)
    
    # 3.2绘制参数2曲线
    x = df['深度'].tolist()
    y = df['参数2'].tolist()
    axes.flatten()[1].plot(x, y, label='参数2', linewidth=1)
    cursor2 = Cursor(axes.flatten()[1], useblit=True, color='red', linewidth=1)
    
    # 3.3绘制参数3曲线
    x = df['深度'].tolist()
    y = df['参数3'].tolist()
    axes.flatten()[2].plot(x, y, label='参数3', linewidth=1)
    cursor3 = Cursor(axes.flatten()[2], useblit=True, color='red', linewidth=1)
    

    这里通过Cursor的构造函数传入需要显示十字光标的子图对象和一些参数,如useblit表示是否使用双缓存技术来提高绘制效率,color和linewidth分别表示光标的颜色和线宽。

    最后,将创建的Cursor对象添加到子图中即可。运行程序后,就可以在每个子图中看到十字光标了。
    我给你浅浅修改了一下你的代码中# 3绘图 的部分:

    # 3绘图
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False
    fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(20, 8)) #将父页面分割成3*1子界面,fig-大画板,axes-相当于图表
    fig.suptitle('总标题', fontsize=14, fontweight='bold')
    axes.flatten()[0].set_title('子图1', fontsize=12)
    axes.flatten()[1].set_title('子图2', fontsize=12)
    axes.flatten()[2].set_title('子图3', fontsize=12)
    fig.subplots_adjust(left=0.05, right=0.95, bottom=0.1, top=0.9, wspace=0.2, hspace=0.4)
    
    # 3.1绘制参数1曲线
    x = df['深度'].tolist()
    y = df['参数1'].tolist()
    axes.flatten()[0].plot(x, y, label='参数1', linewidth=1)
    axes.flatten()[0].set_ylim(400, 800)
    
    # 3.1绘制参数2曲线
    x = df['深度'].tolist()
    y = df['参数2'].tolist()
    axes.flatten()[1].plot(x, y, label='参数2', linewidth=1)
    
    # 3.1绘制参数3曲线
    x = df['深度'].tolist()
    y = df['参数3'].tolist()
    axes.flatten()[2].plot(x, y, label='参数3', linewidth=1)
    
    # 4添加十字光标
    fig.canvas.mpl_connect('motion_notify_event', lambda event: on_move(event, fig, axes))
    
    def on_move(event, fig, axes):
        for ax in axes:
            if ax.contains(event)[0]:
                # 计算光标位置
                x, y = event.xdata, event.ydata
                # 更新垂直线和水平线
                ax.axvline(x=x, color='k', linestyle='--')
                ax.axhline(y=y, color='k', linestyle='--')
                # 更新标题
                ax.set_title(f'子图{axes.index(ax)+1} - x:{x:.2f}, y:{y:.2f}', fontsize=12)
                # 更新画布
                fig.canvas.draw_idle()
    

    回答不易,望采纳

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月27日
  • 已采纳回答 2月19日
  • 赞助了问题酬金15元 2月19日
  • 创建了问题 2月19日

悬赏问题

  • ¥50 三种调度算法报错 有实例
  • ¥15 关于#python#的问题,请各位专家解答!
  • ¥200 询问:python实现大地主题正反算的程序设计,有偿
  • ¥15 smptlib使用465端口发送邮件失败
  • ¥200 总是报错,能帮助用python实现程序实现高斯正反算吗?有偿
  • ¥15 对于squad数据集的基于bert模型的微调
  • ¥15 为什么我运行这个网络会出现以下报错?CRNN神经网络
  • ¥20 steam下载游戏占用内存
  • ¥15 CST保存项目时失败
  • ¥20 java在应用程序里获取不到扬声器设备