【问题标题】:Adding custom buttons to the NavigationToolbarTkAgg向 NavigationToolbarTkAgg 添加自定义按钮
【发布时间】:2018-01-31 17:32:35
【问题描述】:

我有基于 Tkinter 的应用程序,我想为其添加一个自定义按钮,允许用户指定 x 轴和 y 轴,之后 matplotlib 画布将显示指定的轴范围。

我一直在处理其他repo'sSO 和博客posts 上的问题,试图了解如何做到这一点,这让我可以添加自定义按钮,它能够“放大”感兴趣的区域(固定为 [15,45] 以进行测试)但它忘记了它的初始轴(这意味着默认的 homeback 按钮在自定义 @ 之前无法返回任何内容987654327@按钮被按下)。

我的自定义工具栏代码:

# Custom toolbar
class CustomToolbar(NavigationToolbar2TkAgg):
    def plot_axes(self):
        # This function currently makes it so that the 'original view' is lost
        # TODO Fix the above bug
        self.canvas.figure.axes[0].set_xlim([10,60])
        self.canvas.draw()

    def __init__(self,canvas_,parent_):
        self.toolitems = (
            ('Home', 'Reset original view', 'home', 'home'),
            ('Back', 'Back to previous view', 'back', 'back'),
            ('Forward', 'Forward to next view', 'forward', 'forward'),
            ('Pan', 'Pan axes with left mouse, zoom with right', 'move', 'pan'),
            ('Zoom', 'Zoom to rectangle', 'zoom_to_rect', 'zoom'),
            # TODO Get this poor thing a nice gif
            ('Axes', 'Zoom in on region of interest (15-45)', 'subplots', 'plot_axes'),
            ('Subplots', 'Configure subplots', 'subplots', 'configure_subplots'),
            ('Save', 'Save the figure', 'filesave', 'save_figure'),
            )
        NavigationToolbar2TkAgg.__init__(self,canvas_,parent_)

所以问题是,我应该如何更改 xlim 和 ylim 值,以使 GUI 不会忘记初始 xlim/ylim,确保 homeback 按钮仍然按预期工作.

MCVE:

#! /usr/bin/env python

# General imports
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from Tkinter import *
import matplotlib
import random

Xdata = xrange(0,60)
Ydata = random.sample(range(1,100),60)

# Custom toolbar
class CustomToolbar(NavigationToolbar2TkAgg):
    def plot_axes(self):
        # This function currently makes it so that the 'original view' is lost
        # TODO Fix the above bug
        self.canvas.figure.axes[0].set_xlim([15,45])
        self.canvas.draw()

    def __init__(self,canvas_,parent_):
        self.toolitems = (
            ('Home', 'Reset original view', 'home', 'home'),
            ('Back', 'Back to previous view', 'back', 'back'),
            # TODO Get this poor thing a nice gif
            ('Axes', 'Zoom in on region of interest (10-60)', 'subplots', 'plot_axes'),
            )
        NavigationToolbar2TkAgg.__init__(self,canvas_,parent_)

# Functions
def openFile(fig,canvas):
    fig.clear()
    axes = fig.add_subplot(111)
    line, = axes.plot(Xdata,Ydata,label="dummy")
    handles, labels = axes.get_legend_handles_labels()
    fig.legend(handles,labels)
    axes.get_xaxis().get_major_formatter().set_useOffset(False)
    axes.set_xlabel("X")
    axes.set_ylabel("Y")
    canvas.draw()   

# Applicatiom
class App():
    def __init__(self, master):
        # CANVAS
        self.fig = matplotlib.figure.Figure()
        self.canvas = FigureCanvasTkAgg(self.fig, master=master)
        self.toolbar = CustomToolbar(self.canvas, master)
        self.canvas.get_tk_widget().pack(fill=BOTH, expand=YES)
        self.canvas.draw()

        # FRAME
        frame = Frame(master)

        # QUIT
        def close():
            root.destroy()
            root.quit()
        root.protocol("WM_DELETE_WINDOW", lambda: close())

        # MENU
        menu = Menu(master)
        master.config(menu=menu)

        filemenu = Menu(menu, tearoff=0)
        menu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="Open Chromatogram", command=lambda: openFile(self.fig, self.canvas))

# Call the main app
if __name__ == "__main__":
    root = Tk()
    app = App(root)
    root.mainloop()

附加信息:

操作系统:Win7 Py: 2.7.13 (Anaconda 4.3.0) 库:Matplotlib 2.0.0

【问题讨论】:

  • 在我的测试中,“home”和“back”按钮在调用 set_xlim 后仍然有效。也许minimal reproducible example 将有助于发现正在发生的事情。
  • 编辑可能会提供完整且可验证的内容,但我认为它不符合“最小”的条件。如果这确实是一个问题,它应该可以在大约 40 行代码中重现。
  • 确保创建 mcve 需要时间。最好明天问一个好问题,而不是今天问一个不完整的问题。在更新问题或提出新问题时,不要忘记提供有关系统(操作系统、python 和库版本)的信息。
  • @ImportanceOfBeingErnest MCVE 大约 70 行已添加。
  • 存储当前视图self.push_current()

标签: python matplotlib tkinter


【解决方案1】:

在我看来,您只需要在更改限制之前存储当前视图。 IE。添加self.push_current() 可能就足够了。

class CustomToolbar(NavigationToolbar2TkAgg):
    def plot_axes(self):
        self.push_current()   # <--- add this
        self.canvas.figure.axes[0].set_xlim([15,45])
        self.canvas.draw()

注意:在较新版本的 matplotlib 中,您应该使用 NavigationToolbar2Tk 而不是 NavigationToolbar2TkAgg

【讨论】:

  • 确实解决了它;您是否知道任何描述属于该类的所有函数/方法的文档(因为matplotlib.org/api/… 上的描述相当有限)?
  • 好吧,文档本身就是一个好的开始。如果这还不够,您可以随时参考source code,这通常并不难理解。在这里提出问题通常也非常成功(假设它符合How to Ask 并且其中包含 mcve,例如,您在提供 mcve 20 分钟后确实有答案)。
猜你喜欢
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多