matplotlib 如何防止Tkinter GUI中的动画情节出现卡顿?

fiei3ece  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(156)

下面是代码,它显示了一个动画图和一个GUI来显示值:

  1. import random
  2. import time
  3. import tkinter as tk
  4. import matplotlib.pyplot as plt
  5. from matplotlib import animation
  6. import threading
  7. root = tk.Tk()
  8. gui_text = tk.StringVar()
  9. tk.Label(root, textvariable=gui_text).pack()
  10. x = []
  11. y = []
  12. def data_thread():
  13. while True:
  14. random_value = random.random()
  15. x.append(len(x))
  16. y.append(random_value)
  17. gui_text.set(f"Random Value: {random_value:.2f}")
  18. time.sleep(0.09)
  19. def init():
  20. plot_data.set_data([], [])
  21. return (plot_data,)
  22. def animate(frame):
  23. plot_data.set_data(x, y)
  24. plot_axes.relim()
  25. plot_axes.autoscale_view(True)
  26. return (plot_data,)
  27. plot_figure = plt.figure()
  28. plot_axes = plt.axes()
  29. (plot_data,) = plot_axes.plot([], [])
  30. animation = animation.FuncAnimation(plot_figure, animate, init_func=init, interval=1000, blit=False)
  31. plt.show(block=False)
  32. thread = threading.Thread(target=data_thread)
  33. thread.daemon = True
  34. thread.start()
  35. root.mainloop()

正如你所看到的,当情节更新/动画(每秒)时,GUI停止更新值(显示为“随机值:“)有办法防止这种情况吗?

pu3pd22g

pu3pd22g1#

首先,永远不要在Tkinter中使用线程(或者非常小心地使用它),你应该只使用一个循环(mainloop)。这是因为当你使用线程时,tkinter会产生内存泄漏。
其次,animate示例的使用非常复杂。你可以通过清除值并使用新值再次绘制来完成同样的事情(参见下面的代码)。
最后,如果你使用我的代码(它工作正常),但你绘制值非常快,我建议你限制绘制的数字(如果你需要,我可以帮助你)。
在这里,我的代码将每0.01秒获得一个随机值,并直接绘制它。我注解了我的代码,所以它更清晰。
有任何问题都可以问我!祝你有愉快的一天。

  1. import random
  2. import tkinter as tk
  3. import matplotlib.pyplot as plt
  4. from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
  5. class Window(tk.Tk):
  6. def __init__(self,*args):
  7. super().__init__()
  8. #var
  9. self.x_list = [] #list of x position | they need to be the same size
  10. self.y_list = [] #list of y position
  11. self.nbrOfPoints = 0
  12. #widget creation
  13. self.label1 = tk.Label(self) #label displaying random values
  14. self.figure = plt.Figure(figsize=(7,3), dpi=100) #figure that will hold your plot
  15. self.subplot = self.figure.add_subplot(111) #plot holded by figure
  16. self.GraphCanva = FigureCanvasTkAgg(self.figure, master=self) #canvas from figure
  17. self.GraphCanva.get_tk_widget().pack() #place your canvas
  18. #widget placement
  19. self.label1.pack()
  20. self.update_values_to_plot() #launch the loop to updates values to plot
  21. self.update_plot() #lauch loop that will update the plot
  22. def update_values_to_plot(self) :
  23. random_value = self.randomValue() #get a random value between 0.0 and 1.0
  24. self.x_list.append(random_value) #add the random valut to x list
  25. self.y_list.append(self.nbrOfPoints) #add 0, 1, 2 ... to y list
  26. self.nbrOfPoints += 1
  27. #label is a disctionnary so you can update values like this
  28. self.label1['text'] = "Random value : " + str(random_value) #show random value on label
  29. self.after(10, self.update_values_to_plot) #call back this function every 0.5 secs
  30. def randomValue(self) :
  31. return random.random() #return a random value
  32. def update_plot(self) : #update the plot
  33. self.subplot.cla() #clear plot
  34. self.subplot.plot(self.y_list, self.x_list, '-o', label="Random values", color='blue') #place new values
  35. self.GraphCanva.draw_idle() #draw what's in your canva (your plot)
  36. self.after(10, self.update_plot) #call back function every 0.5secs
  37. if __name__ == "__main__":
  38. second_window = Window()
  39. second_window.mainloop()
展开查看全部

相关问题