Tkinter 中的 Matplotlib 图 - 每次更新都会添加新的 NavigationToolbar? [英] Matplotlib plot in Tkinter - every update adds new 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屋!