我正在制作一个应该可视化传感器数据的应用程序。因此,我将tkinter作为gui框架和matplotlib使用python来可视化数据。该图应显示当前传感器值,因此应设置动画。
但是,由于我不希望在未连接传感器时对图形进行动画处理,因此添加了一个connect
按钮,该按钮需要启动动画。
所有这一切都按预期工作,但是,动画仅在我调整tkinter窗口大小后才开始。
我认为这会触发所有组件的重绘,但是我不知道如何从代码中触发它。
我已经尝试调用函数root.update()
和root.update_idletasks()
,但这无济于事。
这是代码的最小示例:
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib import style
root = tk.Tk()
style.use('fivethirtyeight')
ys = [i for i in range(100)]
def animate(i, ax1, line):
global ys
ys = ys[1:] + [ys[0]]
line.set_ydata(ys)
# Draw x and y lists
ax1.relim()
ax1.autoscale_view(True,True,True)
return line
class Gui():
def __init__(self):
global ys
self._fig = plt.figure()
self._ax1 = self._fig.add_subplot(1,1,1)
self._line, = self._ax1.plot(ys)
plt.xticks(ha='right')
plt.subplots_adjust(bottom=0.30)
plt.title('Air pressure measured')
plt.ylabel('Sensor value')
top_frame = tk.Frame(root, bg='cyan', width = 450, height=50)
top_frame.pack(side=tk.LEFT, anchor=tk.N, pady=10)
self.connectButton = tk.Button(top_frame,
text="connect",
command=self.toggleAnimate)
self.connectButton.pack()
self._canvas = FigureCanvasTkAgg(self._fig, master=root)
self._canvas.draw()
self._canvas.get_tk_widget().pack()
def start(self):
root.mainloop()
def toggleAnimate(self):
self._animate = animation.FuncAnimation(self._fig, animate, fargs=(self._ax1, self._line), interval=100, blit=False)
root.update_idletasks()
root.update()
if __name__ == "__main__":
g = Gui()
g.start()
答案 0 :(得分:1)
您需要在draw_idle
上致电FigureCanvasTkAgg
一次,以使事情进展顺利。
我将root
放在GUI内,并删除了对update
和update_idletasks
的不必要的调用,这些调用可能会干扰mainloop
。
我也将您的canvas
包装在frame
内,但是您可以根据需要将其重新定位到root
。
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib import style
style.use('fivethirtyeight')
ys = [i for i in range(100)]
def animate(i, ax1, line):
global ys
ys = ys[1:] + [ys[0]]
line.set_ydata(ys)
# Draw x and y lists
ax1.relim()
ax1.autoscale_view(True,True,True)
return line
class Gui():
def __init__(self):
self.root = tk.Tk()
self._fig = plt.figure()
self._ax1 = self._fig.add_subplot(1,1,1)
self._line, = self._ax1.plot(ys)
plt.xticks(ha='right')
plt.subplots_adjust(bottom=0.30)
plt.title('Air pressure measured')
plt.ylabel('Sensor value')
top_frame = tk.Frame(self.root, bg='cyan', width = 450, height=50)
top_frame.pack(side=tk.LEFT, anchor=tk.N, pady=10)
self.connectButton = tk.Button(top_frame,
text="connect",
command=self.toggleAnimate)
self.connectButton.pack()
self._canvas = FigureCanvasTkAgg(self._fig, master=top_frame) #master=self.root)
self._canvas.get_tk_widget().pack(expand=True, side=tk.LEFT, anchor=tk.N, pady=10, padx=10)
self._canvas.draw()
self._animate = None
def start(self):
self.root.mainloop()
def toggleAnimate(self):
if self._animate is None:
self._canvas.draw_idle()
self._animate = animation.FuncAnimation(self._fig, animate, fargs=(self._ax1, self._line), interval=100) #, blit=False)
if __name__ == "__main__":
g = Gui()
g.start()