Tkinter 中的 Matplotlib 图 - 每次更新都会添加新的 NavigationToolbar? [英] Matplotlib plot in Tkinter - every update adds new NavigationToolbar?

查看:51
本文介绍了Tkinter 中的 Matplotlib 图 - 每次更新都会添加新的 NavigationToolbar?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Tkinter-GUI来交互生成Matplotlib-plots,具体取决于用户输入.为此,需要在用户更改输入后重新绘制.

I am working on a Tkinter-GUI to interactively generate Matplotlib-plots, depending on user-input. For this end, it needs to re-plot after the user changes the input.

我已经使它原则上可以工作,但希望包含 NavigationToolbar .但是,我似乎无法使 NavigationToolbar 的更新正常工作.

I have gotten it to work in principle, but would like to include the NavigationToolbar. However, I cannot seem to get the updating of the NavigationToolbar to work correctly.

这是该代码的基本工作版本(无需用户输入条目):

Here is a basic working version of the code (without the user input Entries):

# Import modules
from Tkinter import *
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg

# global variable: do we already have a plot displayed?
show_plot = False

# plotting function
def plot(x, y):
    fig = plt.figure()
    ax1 = fig.add_subplot(1,1,1)
    ax1.plot(x,y)
    return fig

def main():
    x = np.arange(0.0,3.0,0.01)
    y = np.sin(2*np.pi*x)
    fig = plot(x, y)

    canvas = FigureCanvasTkAgg(fig, master=root)
    toolbar = NavigationToolbar2TkAgg(canvas, toolbar_frame)

    global show_plot
    if show_plot:
        #remove existing plot and toolbar widgets
        canvas.get_tk_widget().grid_forget()
        toolbar_frame.grid_forget()

    toolbar_frame.grid(row=1,column=1)
    canvas.get_tk_widget().grid(row=0,column=1)
    show_plot=True

# GUI
root = Tk()

draw_button = Button(root, text="Plot!", command = main)
draw_button.grid(row=0, column=0)

fig = plt.figure()
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(row=0,column=1)
toolbar_frame = Frame(root)
toolbar_frame.grid(row=1,column=1)

root.mainloop()

按绘图!"一次生成图和 NavigationToolbar .第二次按下它会重新绘制,但会生成一个 second NavigationToolbar(每次按下Plot!"时都会生成另一个).听起来像 grid_forget()无法正常工作.然而,当我改变

Pressing "Plot!" once generates the plot and the NavigationToolbar. Pressing it a second time replots, but generates a second NavigationToolbar (and another every time "Plot!" is pressed). Which sounds like grid_forget() is not working. However, when I change

    if show_plot:
        #remove existing plot and toolbar widgets
        canvas.get_tk_widget().grid_forget()
        toolbar_frame.grid_forget()

    toolbar_frame.grid(row=1,column=1)
    canvas.get_tk_widget().grid(row=0,column=1)
    show_plot=True

    if show_plot:
        #remove existing plot and toolbar widgets
        canvas.get_tk_widget().grid_forget()
        toolbar_frame.grid_forget()
    else:
        toolbar_frame.grid(row=1,column=1)
    canvas.get_tk_widget().grid(row=0,column=1)
    show_plot=True

然后 NavigationToolbar does 在Plot!"时消失再按一次(但是,按预期,没有新的 NavigationToolbar 可以代替旧的).所以 grid_forget() 正在 工作,只是不像预期的那样.

then the NavigationToolbar does vanish when "Plot!" is pressed a second time (but then there is, as expected, no new NavigationToolbar to replace the old). So grid_forget() is working, just not as expected.

我做错了什么?有没有更好的方法来更新 NavigationToolbar ?

What am I doing wrong? Is there a better way to update the NavigationToolbar?

非常感谢任何帮助!拉斯塔尔达

Any help greatly appreciated! Lastalda

我发现如果您销毁 NavigationToolbar 而不是忘记它,这将起作用.但是,您当然必须在之后再次完全重新创建该小部件:

I found that this will work if you destroy the NavigationToolbar instead of forgetting it. But you have to completely re-create the widget again afterwards, of course:

canvas = FigureCanvasTkAgg(fig, master=root)
toolbar_frame = Frame(root)

global show_plot
if show_plot: # if plot already present, remove plot and destroy NavigationToolbar

    canvas.get_tk_widget().grid_forget()
    toolbar_frame.destroy()

toolbar_frame = Frame(root)
toolbar = NavigationToolbar2TkAgg(canvas, toolbar_frame)
toolbar_frame.grid(row=21,column=4,columnspan=3)
canvas.get_tk_widget().grid(row=1,column=4,columnspan=3,rowspan=20)

show_plot = True

但是,下面 Hans 展示的更新方法要好得多,因为您不必销毁和重新创建任何东西.我只是想强调一下我的方法的问题(除了不优雅和性能)可能是我没有使用 destroy().

However, the updating approach showed by Hans below is much nicer since you don't have to destroy and recreate anything. I just wanted to highlight that the issue with my approach (apart from the inelegance and performance) was probably that I didn't use destroy().

推荐答案

一种稍微不同的方法可能是通过清除 &重画它.这样,您就不必破坏 &既不重新生成图形也不重新生成工具栏:

A slightly different approach might be to reuse the figure for subsequent plots by clearing & redrawing it. That way, you don't have to destroy & regenerate neither the figure nor the toolbar:

from Tkinter import Tk, Button
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg

# plotting function: clear current, plot & redraw
def plot(x, y):
    plt.clf()
    plt.plot(x,y)
    # just plt.draw() won't do it here, strangely
    plt.gcf().canvas.draw()

# just to see the plot change
plotShift = 0
def main():
    global plotShift

    x = np.arange(0.0,3.0,0.01)
    y = np.sin(2*np.pi*x + plotShift)
    plot(x, y)

    plotShift += 1

# GUI
root = Tk()

draw_button = Button(root, text="Plot!", command = main)
draw_button.grid(row=0, column=0)

# init figure
fig = plt.figure()

canvas = FigureCanvasTkAgg(fig, master=root)
toolbar = NavigationToolbar2TkAgg(canvas, root)
canvas.get_tk_widget().grid(row=0,column=1)
toolbar.grid(row=1,column=1)

root.mainloop()

这篇关于Tkinter 中的 Matplotlib 图 - 每次更新都会添加新的 NavigationToolbar?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆