Saya sedang melakukan GUI tkinter untuk program saya dan saya harus menampilkan beberapa data waktu nyata. Saya membuat program sederhana (di bawah) untuk menunjukkan masalah saya pada kasus sederhana. Saya sebenarnya memplot beberapa data setiap iterasi untuk loop saya sehingga saya dapat mengamati data saat program masih menghitung. Perhatikan bahwa program sebenarnya menghitung sedikit lebih lambat dan memiliki lebih banyak iterasi.

Sekarang saya ingin menambahkan 2 tombol (satu untuk menjeda program dan satu untuk melanjutkan) dan sebuah label (variabel pemutaran k jadi saya tahu di mana program saya), tetapi saya tidak dapat melakukannya.

Saya sudah kehilangan banyak waktu jadi jika ada yang punya petunjuk atau solusi saya akan senang melihatnya.

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt
from matplotlib import style

def func_A(a, x):
    import numpy
    data_x = numpy.arange(0, x)
    data_y = a * numpy.sin(data_x/5)
    return data_x, data_y

a = 1

root = tk.Tk()
root.title("Graph")
root.geometry("800x400")

fig = plt.figure(figsize=(5, 5), dpi=100)
canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

plt.grid("both")
style.use("ggplot")
for k in range(0, 100):
    data_x, data_y = func_A(a, k)
    print("iteration", k)
    print("data_x", data_x)
    print("data_y", data_y)
    if k == 0:
        ax1 = plt.subplot(111)
        line1, = ax1.plot([0], [0])
    else:
        line1.set_xdata(data_x)
        line1.set_ydata(data_y)

    ax1.set_ylim([-1, 1])
    ax1.set_xlim([0, 100])
    plt.grid("both")
    canvas.draw()
    canvas.flush_events()
root.mainloop()
0
user15854338 27 Mei 2021, 11:45

1 menjawab

Jawaban Terbaik

Untuk menambahkan fungsi jeda/lanjutkan:

  • buat bingkai untuk menahan label kemajuan dan dua tombol: jeda dan lanjutkan
  • buat tkinter BooleanVar() untuk menyimpan status jeda/lanjutkan
  • pindahkan kode plot pembaruan di dalam suatu fungsi, mis. update_plot()
  • gunakan .after() untuk mengganti for loop untuk memanggil update_plot() secara berkala
  • di dalam update_plot(), periksa status jeda/lanjutkan untuk menentukan apakah akan memperbarui plot atau tidak

Di bawah ini adalah contoh yang dimodifikasi berdasarkan kode Anda:

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt
from matplotlib import style
import matplotlib
matplotlib.use("Agg")

root = tk.Tk()
root.title("Graph")
#root.geometry("800x400")

# progress label, pause and resume buttons
frame = tk.Frame(root)
frame.pack(fill="x", side=tk.TOP)

progress = tk.Label(frame)
progress.pack(side="left")

is_paused = tk.BooleanVar()  # variable to hold the pause/resume state
tk.Button(frame, text="Pause", command=lambda: is_paused.set(True)).pack(side="right")
tk.Button(frame, text="Resume", command=lambda: is_paused.set(False)).pack(side="right")

# the plot

fig = plt.figure(figsize=(10, 5), dpi=100)

canvas = FigureCanvasTkAgg(fig, master=root)
toolbar = NavigationToolbar2Tk(canvas, root)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

plt.grid("both")
style.use("ggplot")

a = 1
ax1 = plt.subplot(111)
line1, = ax1.plot([0], [0])

def func_A(a, x):
    import numpy
    data_x = numpy.arange(0, x)
    data_y = a * numpy.sin(data_x/5)
    return data_x, data_y

# function to update ploat
def update_plot(k=0):
    if not is_paused.get():
        progress["text"] = f"iteration: {k}"

        data_x, data_y = func_A(a, k)
        #print("iteration", k)
        #print("data_x", data_x)
        #print("data_y", data_y)

        line1.set_xdata(data_x)
        line1.set_ydata(data_y)

        ax1.set_ylim([-1, 1])
        ax1.set_xlim([0, 100])
        plt.grid("both")
        canvas.draw()
        canvas.flush_events()
        k += 1
    if k <= 100:
        # update plot again after 10ms. You can change the delay to whatever you want
        root.after(10, update_plot, k)

update_plot() # start updating plot
root.mainloop()
0
acw1668 27 Mei 2021, 10:10