如何为Matplotlib交互式绘图工具栏添加信息弹窗按钮
Matplotlib自定义工具栏:添加显示绘图数据的按钮
Matplotlib的绘图工具栏支持自定义功能,官方提供了示例代码实现数据的隐藏/显示功能,示例界面如下:

官方示例代码
import matplotlib.pyplot as plt from matplotlib.backend_tools import ToolBase, ToolToggleBase plt.rcParams['toolbar'] = 'toolmanager' class ListTools(ToolBase): """列出ToolManager控制的所有工具""" default_keymap = 'm' # 快捷键 description = '列出工具' def trigger(self, *args, **kwargs): print('_' * 80) fmt_tool = "{:12} {:45} {}".format print(fmt_tool('名称(ID)', '工具描述', '快捷键')) print('-' * 80) tools = self.toolmanager.tools for name in sorted(tools): if not tools[name].description: continue keys = ', '.join(sorted(self.toolmanager.get_tool_keymap(name))) print(fmt_tool(name, tools[name].description, keys)) print('_' * 80) fmt_active_toggle = "{0!s:12} {1!s:45}".format print("激活的切换工具") print(fmt_active_toggle("分组", "激活项")) print('-' * 80) for group, active in self.toolmanager.active_toggle.items(): print(fmt_active_toggle(group, active)) class GroupHideTool(ToolToggleBase): """显示指定gid的线条""" default_keymap = 'S' description = '按gid显示' default_toggled = True def __init__(self, *args, gid, **kwargs): self.gid = gid super().__init__(*args, **kwargs) def enable(self, *args): self.set_lines_visibility(True) def disable(self, *args): self.set_lines_visibility(False) def set_lines_visibility(self, state): for ax in self.figure.get_axes(): for line in ax.get_lines(): if line.get_gid() == self.gid: line.set_visible(state) self.figure.canvas.draw() fig = plt.figure() plt.plot([1, 2, 3], gid='mygroup') plt.plot([2, 3, 4], gid='unknown') plt.plot([3, 2, 1], gid='mygroup') # 添加自定义工具 fig.canvas.manager.toolmanager.add_tool('List', ListTools) fig.canvas.manager.toolmanager.add_tool('Show', GroupHideTool, gid='mygroup') # 将现有工具添加到新分组`foo` fig.canvas.manager.toolbar.add_tool('zoom', 'foo') # 移除前进按钮 fig.canvas.manager.toolmanager.remove_tool('forward') # 将自定义工具添加到导航分组的指定位置 fig.canvas.manager.toolbar.add_tool('Show', 'navigation', 1) plt.show()
需求:添加按钮点击后在新窗口显示绘图数据文本
要实现点击工具栏按钮后弹出新窗口展示绘图数据的文本信息,可以基于ToolBase自定义工具类,结合Matplotlib默认后端的Tkinter库创建窗口。
实现方案
- 自定义继承
ToolBase的工具类,在trigger方法中创建新窗口并提取、格式化绘图数据。 - 使用Tkinter的滚动文本组件展示数据,适配大量数据的查看需求。
- 将自定义工具添加到工具栏的指定位置。
完整示例代码
import matplotlib.pyplot as plt from matplotlib.backend_tools import ToolBase, ToolToggleBase import tkinter as tk from tkinter import scrolledtext plt.rcParams['toolbar'] = 'toolmanager' # 保留官方示例的自定义工具 class ListTools(ToolBase): """列出ToolManager控制的所有工具""" default_keymap = 'm' # 快捷键 description = '列出工具' def trigger(self, *args, **kwargs): print('_' * 80) fmt_tool = "{:12} {:45} {}".format print(fmt_tool('名称(ID)', '工具描述', '快捷键')) print('-' * 80) tools = self.toolmanager.tools for name in sorted(tools): if not tools[name].description: continue keys = ', '.join(sorted(self.toolmanager.get_tool_keymap(name))) print(fmt_tool(name, tools[name].description, keys)) print('_' * 80) fmt_active_toggle = "{0!s:12} {1!s:45}".format print("激活的切换工具") print(fmt_active_toggle("分组", "激活项")) print('-' * 80) for group, active in self.toolmanager.active_toggle.items(): print(fmt_active_toggle(group, active)) class GroupHideTool(ToolToggleBase): """显示指定gid的线条""" default_keymap = 'S' description = '按gid显示' default_toggled = True def __init__(self, *args, gid, **kwargs): self.gid = gid super().__init__(*args, **kwargs) def enable(self, *args): self.set_lines_visibility(True) def disable(self, *args): self.set_lines_visibility(False) def set_lines_visibility(self, state): for ax in self.figure.get_axes(): for line in ax.get_lines(): if line.get_gid() == self.gid: line.set_visible(state) self.figure.canvas.draw() # 新增:显示绘图数据的自定义工具 class ShowDataTool(ToolBase): """在新窗口显示绘图数据详情""" default_keymap = 'd' # 快捷键 description = '显示绘图数据' def trigger(self, *args, **kwargs): # 创建新窗口 data_window = tk.Toplevel() data_window.title("绘图数据详情") data_window.geometry("600x400") # 创建带滚动的文本框 text_area = scrolledtext.ScrolledText(data_window, wrap=tk.WORD, width=70, height=20) text_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True) # 提取并格式化所有绘图数据 data_text = "绘图数据详情:\n" + "-"*50 + "\n" for ax_idx, ax in enumerate(self.figure.get_axes(), 1): data_text += f"\n坐标轴 {ax_idx}:\n" for line_idx, line in enumerate(ax.get_lines(), 1): x_data = line.get_xdata() y_data = line.get_ydata() gid = line.get_gid() or "无gid" label = line.get_label() or "无标签" data_text += f"线条 {line_idx} | 标签: {label} | gid: {gid}\n" data_text += f"X数据: {x_data}\n" data_text += f"Y数据: {y_data}\n" data_text += "-"*30 + "\n" # 插入数据并设置只读 text_area.insert(tk.INSERT, data_text) text_area.config(state=tk.DISABLED) # 创建绘图 fig = plt.figure() plt.plot([1, 2, 3], gid='mygroup', label='上升线条') plt.plot([2, 3, 4], gid='unknown', label='持续上升') plt.plot([3, 2, 1], gid='mygroup', label='下降线条') plt.legend() # 添加所有自定义工具 fig.canvas.manager.toolmanager.add_tool('List', ListTools) fig.canvas.manager.toolmanager.add_tool('Show', GroupHideTool, gid='mygroup') # 添加显示数据工具到导航分组的第3个位置(索引从0开始) fig.canvas.manager.toolmanager.add_tool('ShowData', ShowDataTool) fig.canvas.manager.toolbar.add_tool('ShowData', 'navigation', 2) # 移除前进按钮 fig.canvas.manager.toolmanager.remove_tool('forward') plt.show()
关键说明
- 自定义工具类:
ShowDataTool继承ToolBase,trigger方法是按钮点击后的执行逻辑,负责创建窗口和展示数据。 - 数据提取:通过
line.get_xdata()、line.get_ydata()获取线条的坐标数据,同时可提取gid、标签等附加信息。 - 窗口组件:使用
scrolledtext.ScrolledText实现带滚动的文本展示,避免数据过长无法完全显示。 - 工具栏集成:通过
add_tool方法将自定义工具添加到指定分组,控制其在工具栏中的位置。
内容的提问来源于stack exchange,提问作者Delosari
相关产品推荐
相关产品推荐

