2012-10-17 90 views
3

我正在使用Tkinter-GUI交互式生成Matplotlib圖,具體取決於用戶輸入。爲此,需要在用戶更改輸入後重新繪製。Tkinter中的Matplotlib圖 - 每次更新都會添加新的NavigationToolbar?

我得到它的工作原理,但想包括NavigationToolbar。但是,我似乎無法獲得更新的NavigationToolbar正常工作。

下面是代碼的基本工作版本(無需用戶輸入項):「情節」

# 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。 按它第二次replots,但生成NavigationToolbar(另有每次「情節!」被按下)。這聽起來像grid_forget()不起作用。 但是,當我改變

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確實消失時, 「情節!」再次按下(但如預期的那樣,沒有新的NavigationToolbar替代舊的)。所以grid_forget()工作,只是不如預期。

我在做什麼錯?有沒有更好的方法來更新NavigationToolbar

任何幫助非常感謝! Lastalda

編輯:

我發現,如果你破壞了NavigationToolbar而不是遺忘它,這將工作。但是,你必須完全執行後再次重建過程中的小部件,:

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()

回答

4

稍微不同的方法可能是通過重新繪製&來重複使用該圖形以用於後續繪圖。這樣,你不必破壞&重新生成既不圖形也不是工具欄:

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() 
+0

謝謝!我曾經在各種渠道看到過對'plt.draw()'的引用,但它並不起作用,這就是爲什麼我採用了銷燬和重新創建的方法。但是,這當然好多了。謝謝! – Lastalda

0

當您按下「Plot!」按鈕它調用mainmain創建導航工具欄。所以,每次按下按鈕,您都會看到一個工具欄。我對matplot瞭解不多,但很明顯你爲什麼得到多個工具欄。

順便說一句,grid_forget不破壞部件,它只是從視圖中移除。即使你沒有看到,它仍然在記憶中。

通常在GUI中,您只需創建一次所有的小部件,而不是一遍又一遍地重新創建相同的小部件。

+0

我以爲這麼多。但是,「NavigationToolbar」似乎只有在重新繪製後「刷新」時才起作用(所以它保持連接到新的繪圖)。而且我還沒有找到任何可用的更新類功能。 (如果有人能指點我,請做!)因此,我認爲銷燬和重新創建它們應該有效,我正在嘗試使用'grid_forget()' - 是否有更好的方法呢?另外,我也對畫布部件做了同樣的事情,但在那裏我沒有得到同樣的倍增行爲。我不懂爲什麼。 – Lastalda

相關問題