python matplotlib工具栏源码探析二之添加、删除内置工具项的案例

本文详细介绍了如何在matplotlib中通过工具栏管理器模式来添加、删除内置工具项,以及自定义工具栏布局,以满足高级用户的需求。

matplotlib工具栏源码探析一(禁用工具栏、默认工具栏和工具栏管理器三种模式的差异) 一文可知 matplotlib 内置实现了多个工具项的实现,而默认工具栏中的工具项只是其中的一部分,有没有方法直接管理工具栏,添加、删除内置工具项?

matplotlib内置的工具项

由源码可知, matplotlib.backend_tools.default_tools 变量为字典类型,实例化了基于 matplotlib.backend_tools.ToolBase 类定义的内置工具项。

源码

​
    default_tools = {'home': ToolHome, 'back': ToolBack, 'forward': ToolForward,
         'zoom': ToolZoom, 'pan': ToolPan,
         'subplots': 'ToolConfigureSubplots',
         'save': 'ToolSaveFigure',
         'grid': ToolGrid,
         'grid_minor': ToolMinorGrid,
         'fullscreen': ToolFullScreen,
         'quit': ToolQuit,
         'quit_all': ToolQuitAll,
         'allnav': _ToolEnableAllNavigation,
         'nav': _ToolEnableNavigation,
         'xscale': ToolXScale,
         'yscale': ToolYScale,
         'position': ToolCursorPosition,
         _views_positions: ToolViewsPositions,
         'cursor': 'ToolSetCursor',
         'rubberband': 'ToolRubberband',
         'help': 'ToolHelp',
         'copy': 'ToolCopyToClipboard',
         }

验证

​
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    from pprint import pprint
    
    plt.rcParams['toolbar'] = 'toolmanager'
    fig = plt.gcf()
    pprint(mpl.backend_tools.default_tools)

输出

{'allnav': <class 'matplotlib.backend_tools.ToolEnableAllNavigation'>, 'back': <class 'matplotlib.backend_tools.ToolBack'>, 'copy': 'ToolCopyToClipboard', 'cursor': 'ToolSetCursor', 'forward': <class 'matplotlib.backend_tools.ToolForward'>, 'fullscreen': <class 'matplotlib.backend_tools.ToolFullScreen'>, 'grid': <class 'matplotlib.backend_tools.ToolGrid'>, 'grid_minor': <class 'matplotlib.backend_tools.ToolMinorGrid'>, 'help': 'ToolHelp', 'home': <class 'matplotlib.backend_tools.ToolHome'>, 'nav': <class 'matplotlib.backend_tools.ToolEnableNavigation'>, 'pan': <class 'matplotlib.backend_tools.ToolPan'>, 'position': <class 'matplotlib.backend_tools.ToolCursorPosition'>, 'quit': <class 'matplotlib.backend_tools.ToolQuit'>, 'quit_all': <class 'matplotlib.backend_tools.ToolQuitAll'>, 'rubberband': 'ToolRubberband', 'save': 'ToolSaveFigure', 'subplots': 'ToolConfigureSubplots', 'viewpos': <class 'matplotlib.backend_tools.ToolViewsPositions'>, 'xscale': <class 'matplotlib.backend_tools.ToolXScale'>, 'yscale': <class 'matplotlib.backend_tools.ToolYScale'>, 'zoom': <class 'matplotlib.backend_tools.ToolZoom'>}

使用工具栏管理器管理内置工具项

由源码可知默认工具栏模式 toolbar2 模式没有提供添加、删除工具项的接口。因此,管理工具栏需要使用工具栏管理器模式 toolmanager ,与该模式相关的重要定义有:

  • matplotlib.backend_bases.ToolContainerBase(toolmanager) 类:工具栏容器的基类,定义了工具栏编辑的方法。构造函数参数为 toolmanager ,表示工具栏容器容纳的工具栏。

  • matplotlib.backend_managers.ToolManager(figure=None) 类:管理用户触发工具栏工具项按钮而产生的动作。 matplotlib.backend_tools.ToolBase 类:所有工具栏工具项的基类,所有工具项均由 matplotlib.backend_managers.ToolManager 实例化。

  • matplotlib.backend_tools.default_tools 变量:字典类型,实例化基于 matplotlib.backend_tools.ToolBase 类定义的内置工具项。

  • matplotlib.backend_tools.default_toolbar_tools 变量:嵌套列表,以类似格式 [[分组1, [工具1, 工具2 ...]], [分组2, [...]]] 定义工具栏布局。

  • matplotlib.backend_tools.add_tools_to_container 函数:设置 toolbarmanager 模式默认工具栏。

使用系统函数实现添加工具项

根据源码可知, matplotlib.backend_tools.add_tools_to_container 函数可以设置 toolbarmanager 模式默认工具栏。

案例

案例说明:为工具栏添加 全屏切换 工具项。

​
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    
    plt.rcParams['toolbar'] = 'toolmanager'
    fig = plt.gcf()
    # 通过mpl.backend_tools.add_tools_to_container函数添加工具项
    mpl.backend_tools.add_tools_to_container(fig.canvas.manager.toolbar, tools=[['foo', [ 'fullscreen']]])
    plt.show()

案例解析: add_tools_to_container 函数有两个参数 containertools ,由源码可知 container 参数的值应为 fig.canvas.manager.toolbartools 参数按照 [[分组1, [工具1, 工具2 ...]], [分组2, [...]]] 格式取值。

在这里插入图片描述

使用工具栏管理器实现添加、删除内置工具项

根据源码可知:

添加内置工具项有两种方法

  • toolbar 对象可以通过 add_tool 方法添加内置工具项,参数为 nametoolname 为工具项的名称, tool 为添加的工具项对应的类或者字符串。

  • toolbar 对象可以通过 add_toolitem 方法添加内置工具项,参数为 namegrouppositionimage_filedescriptiontogglename 为工具项的名称, group 为工具项所在组, position 为工具项在组中的位置,取值为列表索引,一般取 -1 即在所在组末尾追加,设置为 0 即在所在组的首位, image_file 为工具项图像,值为字符串, description 为工具项描述, toggle 为是否为切换式工具项,布尔值。

  • 删除内置工具项有两种方法

  • toolbar 对象可以通过 remove_toolitem 方法删除内置工具项,参数为 name ,即工具项的名称。

  • toolmanager 对象可以通过 remove_tool 方法删除内置工具项,参数为 name ,即工具项的名称。

案例

案例说明:删除 向前 工具项,添加 全屏切换 工具项。

​
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    
    plt.rcParams['toolbar'] = 'toolmanager'
    fig = plt.gcf()
    
    fig.canvas.manager.toolmanager.remove_tool('forward')
    fig.canvas.manager.toolbar.remove_toolitem('back')
    fig.canvas.manager.toolbar.add_tool('quit', 'foo')
    fig.canvas.manager.toolbar.add_toolitem('fullscreen', 'foo', -1,'fullscreen','fullscreen',False) 
    
    plt.show()

在这里插入图片描述

总结

通过工具栏管理器添加、删除内置工具项的方法很多种,需要注意调用对象、方法、参数,阅读下面的 matplotlib 源码可能会有所启发。

相关源码

matplotlib.backends.backend_qt5 模块

​
    class FigureManagerQT(FigureManagerBase):
     self.toolbar = self._get_toolbar(self.canvas, self.window)
    
     if self.toolmanager:
      backend_tools.add_tools_to_manager(self.toolmanager)
      if self.toolbar:
       backend_tools.add_tools_to_container(self.toolbar)
    
     if self.toolbar:
      self.window.addToolBar(self.toolbar)
      tbs_height = self.toolbar.sizeHint().height()
     else:
      tbs_height = 0
​
     def _get_toolbar(self, canvas, parent):
      # must be inited after the window, drawingArea and figure
      # attrs are set
      if matplotlib.rcParams['toolbar'] == 'toolbar2':
       toolbar = NavigationToolbar2QT(canvas, parent, True)
      elif matplotlib.rcParams['toolbar'] == 'toolmanager':
       toolbar = ToolbarQt(self.toolmanager, self.window)
      else:
       toolbar = None
      return toolbar
​
     class ToolbarQt(ToolContainerBase, QtWidgets.QToolBar):
     def __init__(self, toolmanager, parent):
      ToolContainerBase.__init__(self, toolmanager)
      QtWidgets.QToolBar.__init__(self, parent)
      self.setAllowedAreas(
       QtCore.Qt.TopToolBarArea | QtCore.Qt.BottomToolBarArea)
      message_label = QtWidgets.QLabel("")
      message_label.setAlignment(
       QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
      message_label.setSizePolicy(
       QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
             QtWidgets.QSizePolicy.Ignored))
      self._message_action = self.addWidget(message_label)
      self._toolitems = {}
      self._groups = {}
    
     def add_toolitem(
       self, name, group, position, image_file, description, toggle):
    
      button = QtWidgets.QToolButton(self)
      if image_file:
       button.setIcon(NavigationToolbar2QT._icon(self, image_file))
      button.setText(name)
      if description:
       button.setToolTip(description)
    
      def handler():
       self.trigger_tool(name)
      if toggle:
       button.setCheckable(True)
       button.toggled.connect(handler)
      else:
       button.clicked.connect(handler)
    
      self._toolitems.setdefault(name, [])
      self._add_to_group(group, name, button, position)
      self._toolitems[name].append((button, handler))
    
     def _add_to_group(self, group, name, button, position):
      gr = self._groups.get(group, [])
      if not gr:
       sep = self.insertSeparator(self._message_action)
       gr.append(sep)
      before = gr[position]
      widget = self.insertWidget(before, button)
      gr.insert(position, widget)
      self._groups[group] = gr
    
     def toggle_toolitem(self, name, toggled):
      if name not in self._toolitems:
       return
      for button, handler in self._toolitems[name]:
       button.toggled.disconnect(handler)
       button.setChecked(toggled)
       button.toggled.connect(handler)
    
     def remove_toolitem(self, name):
      for button, handler in self._toolitems[name]:
       button.setParent(None)
      del self._toolitems[name]
    
     def set_message(self, s):
      self.widgetForAction(self._message_action).setText(s

matplotlib.backend_tools 模块

​
    def add_tools_to_container(container, tools=default_toolbar_tools):
     """
     Add multiple tools to the container.
    
     Parameters
     ----------
     container : Container
      `backend_bases.ToolContainerBase` object that will get the tools added.
     tools : list, optional
      List in the form ``[[group1, [tool1, tool2 ...]], [group2, [...]]]``
      where the tools ``[tool1, tool2, ...]`` will display in group1.
      See `add_tool` for details.
     """
    
     for group, grouptools in tools:
      for position, tool in enumerate(grouptools):
       container.add_tool(tool, group, position)
    def add_tools_to_manager(toolmanager, tools=default_tools):
     """
     Add multiple tools to a `.ToolManager`.
    
     Parameters
     ----------
     toolmanager : `.backend_managers.ToolManager`
      Manager to which the tools are added.
     tools : {str: class_like}, optional
      The tools to add in a {name: tool} dict, see `add_tool` for more
      info.
     """
    
     for name, tool in tools.items():
      toolmanager.add_tool(name, tool)

到此这篇关于python matplotlib工具栏源码探析二之添加、删除内置工具项的案例的文章就介绍到这了,更多相关python matplotlib内置工具项内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

 

<think>我们已经在Qt中集成了Matplotlib的画布,现在需要添加工具栏(包含缩放、保存等功能) 参考引用[2]中提到:使用`NavigationToolbar2QT`作为工具栏,并将其添加到布局中。 步骤: 1. 导入工具栏类:`from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar` 2. 在创建画布后,创建工具栏对象,并传入画布和父窗口(可选)。 3. 将工具栏添加到布局中(通常在画布的上方或下方)。 注意:工具栏需要和画布在同一个容器中,因此我们将其添加到同一个布局中(垂直布局,先工具栏再画布,或者先画布再工具栏都可以,但通常工具栏放在画布上方)。 修改之前的代码: 在`MainWindow`类的`__init__`方法中,创建画布后,创建工具栏,并添加到布局。 示例代码修改如下:</think>### 在PyQt中集成Matplotlib工具栏的完整指南 在PyQt中添加Matplotlib工具栏(缩放/保存功能)需要以下步骤: #### 1. 导入必要的工具栏模块 ```python from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar ``` #### 2. 创建工具栏添加到布局 在窗口初始化方法中添加: ```python class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) # 创建Matplotlib画布 self.figure = Figure(figsize=(5, 4), dpi=100) self.canvas = FigureCanvas(self.figure) # 创建工具栏添加到布局 self.toolbar = NavigationToolbar(self.canvas, self) # 关键步骤 layout = QtWidgets.QVBoxLayout(self.plotWidget) layout.addWidget(self.toolbar) # 先添加工具栏 layout.addWidget(self.canvas) # 再添加画布 # 连接按钮信号 self.plotButton.clicked.connect(self.plot_data) ``` #### 3. 完整实现示例 ```python import sys import matplotlib matplotlib.use('Qt5Agg') from PyQt5 import QtWidgets from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar from matplotlib.figure import Figure from ui_mainwindow import Ui_MainWindow class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) # 创建Matplotlib组件 self.figure = Figure(figsize=(5, 4), dpi=100) self.canvas = FigureCanvas(self.figure) # 创建工具栏添加到布局 self.toolbar = NavigationToolbar(self.canvas, self) layout = QtWidgets.QVBoxLayout(self.plotWidget) layout.addWidget(self.toolbar) layout.addWidget(self.canvas) # 连接按钮信号 self.plotButton.clicked.connect(self.plot_data) def plot_data(self): """绘制示例图表""" ax = self.figure.add_subplot(111) ax.clear() # 生成示例数据 import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) ax.plot(x, y, 'b-', linewidth=2) ax.set_title('带工具栏Matplotlib图表', fontsize=12) ax.set_xlabel('X轴', fontsize=10) ax.set_ylabel('Y轴', fontsize=10) ax.grid(True, linestyle='--', alpha=0.7) self.figure.tight_layout() # 自动调整布局 self.canvas.draw() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` #### 工具栏功能说明 默认工具栏包含以下功能按钮: 1. **主页**:重置原始视图 2. **后退**:返回上一个视图 3. **前进**:前进到下一个视图 4. **平移**:按住左键拖动平移图表 5. **缩放**:框选区域放大 6. **保存**:将图表保存为图像文件(支持PNG/SVG/PDF等格式) 7. **自定义**:添加其他工具(如子图配置) #### 自定义工具栏 ```python # 移除需要的按钮 self.toolbar.actions()[0].setVisible(False) # 隐藏"主页"按钮 # 添加自定义工具 from matplotlib.widgets import Cursor cursor_tool = Cursor(ax, useblit=True, color='red', linewidth=1) self.toolbar.addSeparator() self.toolbar.addAction("十字线", cursor_tool.set_active) ``` #### 常见问题解决 1. **工具栏显示**: - 检查布局是否正确添加工具栏对象 - 确认父窗口设置正确:`NavigationToolbar(self.canvas, self)` - 验证布局管理器是否已应用到容器 2. **保存功能优化**: ```python # 设置默认保存路径和格式 from matplotlib.backends.backend_qt5 import _create_qApp _create_qApp() self.toolbar.set_filetypes([ ('PNG 文件', '*.png'), ('SVG 矢量图', '*.svg'), ('PDF 文档', '*.pdf'), ('所有文件', '*.*') ]) ``` 3. **工具栏样式美化**: ```python # 设置工具栏样式 self.toolbar.setStyleSheet(""" QToolBar { background-color: #f0f0f0; border: 1px solid #d0d0d0; spacing: 3px; padding: 2px; } QToolButton { background-color: #e0e0e0; border-radius: 4px; padding: 3px; } """) ``` #### 进阶技巧:动态更新工具栏 ```python # 响应图表变化更新工具栏状态 def update_toolbar(self): self.toolbar.update() # 刷新工具栏按钮状态 self.toolbar.push_current() # 将当前视图加入历史记录 # 在绘图方法中调用 def plot_data(self): # ...绘图代码... self.canvas.draw() self.update_toolbar() # 更新工具栏 ``` 通过以上步骤,您可以在PyQt应用中轻松添加功能完整的Matplotlib工具栏,实现图表的交互式操作和导出功能[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值