3

私はTkinter-GUIに取り組んでおり、ユーザー入力に応じてMatplotlib-plotsをインタラクティブに生成しています。このためには、ユーザーが入力を変更した後に再プロットする必要があります。

原則として動作するようになりましたが、を含めたいと思いますNavigationToolbarNavigationToolbarただし、の更新を正しく機能させることができないようです。

コードの基本的な作業バージョンは次のとおりです(ユーザー入力エントリなし)。

# 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。2回押すと再プロットされますが、1 NavigationToolbarが生成されます(「Plot!」が押されるたびにもう1回)。どちらが機能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

2 に答える 2

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()
于 2012-10-20T09:44:25.427 に答える
0

「プロット!」を押すと ボタンを呼び出しますmainmainナビゲーションツールバーを作成します。したがって、ボタンを押すたびにツールバーが表示されます。matplotについてはよくわかりませんが、複数のツールバーを使用する理由は明らかです。

ちなみに、grid_forgetウィジェットを破壊するのではなく、単にビューから削除するだけです。あなたがそれを見なくても、それはまだ記憶に残っています。

通常、GUIでは、同じウィジェットを何度も再作成するのではなく、すべてのウィジェットを1回だけ作成します。

于 2012-10-17T11:33:51.977 に答える