Python 如何在matplotlib和tkinter中提示动画时刷新
我试图提示刷新动画绘图,但显然函数Python 如何在matplotlib和tkinter中提示动画时刷新,python,matplotlib,animation,tkinter,Python,Matplotlib,Animation,Tkinter,我试图提示刷新动画绘图,但显然函数FuncAnimation()等待刷新和最后一个间隔条目,我想覆盖它。我的目标:我希望让绘图非常缓慢地更新,例如每分钟更新一次,但在提示或事件时刷新(此事件是一个参数条目) 让我一步一步地解释我的tkinter应用程序是如何工作的。我将在最后发布整个代码 为了这篇文章,我把我的应用程序缩减到最低限度。该应用程序包含一个绘图面板和一个带有命令的侧面板。该应用程序由包含菜单栏的主类plotApp()和两个Pananel组成。这两个面板是两个tk帧,编码成一个单独的类
FuncAnimation()
等待刷新和最后一个间隔条目,我想覆盖它。我的目标:我希望让绘图非常缓慢地更新,例如每分钟更新一次,但在提示或事件时刷新(此事件是一个参数条目)
让我一步一步地解释我的tkinter应用程序是如何工作的。我将在最后发布整个代码
为了这篇文章,我把我的应用程序缩减到最低限度。该应用程序包含一个绘图面板和一个带有命令的侧面板。该应用程序由包含菜单栏的主类plotApp()
和两个Pananel组成。这两个面板是两个tk帧,编码成一个单独的类Graph()
和Commands()
。然后使用函数show\u frame()
引发这些问题。
Graph()
部件使用对象f=plt.figure()
初始化绘图区域。Commands()
部分包含tk输入方法,因此我可以插入参数my_参数
。插入my_参数
后,函数animate()
将执行嵌入绘图的部分
问题是。绘图数据由大型查询x,y=my\u big\u query\u命令(my\u参数)
检索。我必须降低查询更新的频率,比如每分钟一次——数据不会有太大变化。然而,当我设置interval=60000
(毫秒)并输入新参数时,函数FuncAnimation()
会等待整整一分钟来更新查询和绘图。目标1:我希望他们能立即更新。目标2:我希望保持(或重置)一分钟的慢节奏。我该怎么做
到目前为止我都试过了。为了重复性,我用简单的数据替换了对数据x,y
的查询。输入参数my_parameter时,函数toggle_refresh_plot()
将激活标志以运行查询和打印。这发生在类Commands()
的函数set\u entry()
中
我还尝试从set\u entry()
中调用函数animate()
,但没有用
然后,我在函数animate()
中嵌入了if
语句。如果标志为True
,则调用查询和绘图。查询之后,我使用命令ani.event\u source.interval=slow\u refresh
将速度设置为一分钟,其中ani
对象定义为animation.FuncAnimation(f,animate,interval=slow\u refresh)
。如果标志为False
,则间隔将缩短为1秒,这样应用程序可以更快地听到我的提示,而无需刷新繁重的查询。命令ani.event\u source.interval
起作用,但效果并不理想:它在输入后仍会等待整整一分钟
def animate(i):
print("refresh_flag", refresh_flag)
if refresh_flag:
try:
# query data here
# ...
# plot here
# ...
print('refreshed: ', datetime.today())
except Exception as e:
print("error message:", str(e))
ani.event_source.interval = slow_refresh # after query slow down pace
else:
ani.event_source.interval = 1000 # every second
# ani.event_source.interval = slow_refresh
函数animate()
中的print()
命令显示何时调用查询和绘图
我在冻结模式下初始化应用程序,即refresh\u flag=False
,慢60秒slow\u refresh=60*1000
,空my\u参数=“”
菜单中还有一个刷新命令,用于控制功能切换\u Refresh\u plot()
下面是整个代码
from datetime import datetime, timedelta
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
from tkinter import ttk
def toggle_refresh_plot(toggle):
global refresh_flag
if toggle == 'resume':
refresh_flag = True
elif toggle == 'freeze':
refresh_flag = False
def animate(i):
print("refresh_flag", refresh_flag)
if refresh_flag:
try:
# query data here
# x, y = my_big_query_command(my_parameter)
x = np.arange(10)
y = np.sqrt(x)
a1 = plt.subplot2grid((1, 2), (0, 0), rowspan=1, colspan=1)
a2 = plt.subplot2grid((1, 2), (0, 1), sharey=a1, rowspan=1, colspan=1)
plt.subplots_adjust(wspace=0.2)
a1.plot(x, y, 'b-')
a2.plot(x, x / (y + 1), 'b-')
print('refreshed: ', datetime.today())
except Exception as e:
print("error message:", str(e))
ani.event_source.interval = slow_refresh # after query slow down pace
else:
ani.event_source.interval = 1000 # every second
# ani.event_source.interval = slow_refresh
class plotApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Plotting App")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
menubar = tk.Menu(container)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=quit)
menubar.add_cascade(label="File", menu=filemenu)
startStop = tk.Menu(menubar, tearoff=1)
startStop.add_command(label="Resume", command=lambda: toggle_refresh_plot('resume'))
startStop.add_command(label="Freeze", command=lambda: toggle_refresh_plot('freeze'))
menubar.add_cascade(label="Refresh", menu=startStop)
tk.Tk.config(self, menu=menubar)
self.frames = {} # initialize empty frames
# build Graph frame
frame = Graph(container, self)
self.frames[Graph] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Graph)
# build Commands frame
frame = Commands(container, self)
self.frames[Commands] = frame
frame.grid(row=0, column=1)
self.show_frame(Commands)
def show_frame(self, frame_name):
frame = self.frames[frame_name]
frame.tkraise()
class Commands(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.parent = parent
side_frame = tk.Frame(self)
side_frame.pack()
Lab1 = tk.Label(side_frame, text="Insert name", anchor=tk.W)
Lab1.grid(row=1, column=0)
def set_entry(self):
global my_parameter
my_parameter = (e1.get())
print("Entry:", my_parameter)
toggle_refresh_plot('resume')
e1 = ttk.Entry(side_frame)
e1.bind("<Return>", set_entry)
e1.grid(row=2, column=0)
class Graph(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
f = plt.figure()
# a1 = f.add_subplot(111)
refresh_flag = False
slow_refresh = 60 * 1000 # refresh plot every 60 sec
my_parameter = '' # initialize as empty
app = plotApp()
ani = animation.FuncAnimation(f, animate, interval=slow_refresh) # update chart every 'interval' milliseconds
app.mainloop()
从datetime导入datetime,timedelta
将numpy作为np导入
从matplotlib导入pyplot作为plt
将matplotlib.animation导入为动画
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG,导航工具栏2TK
将tkinter作为tk导入
从tkinter导入ttk
def切换\刷新\绘图(切换):
全局刷新标志
如果切换==“恢复”:
刷新标志=True
elif切换==“冻结”:
刷新标志=False
定义动画(i):
打印(“刷新标志”,刷新标志)
如果刷新\u标志:
尝试:
#在此查询数据
#x,y=my\u big\u query\u命令(my\u参数)
x=np.arange(10)
y=np.sqrt(x)
a1=plt.subplot2grid((1,2)、(0,0),rowspan=1,colspan=1)
a2=plt.subplot2grid((1,2)、(0,1),sharey=a1,rowspan=1,colspan=1)
plt.子批次调整(wspace=0.2)
a1.图(x,y,'b-')
a2.图(x,x/(y+1),‘b-’)
打印('刷新:',datetime.today())
例外情况除外,如e:
打印(“错误消息:”,str(e))
ani.event_source.interval=慢_刷新#查询后慢节奏
其他:
ani.event_source.interval=1000#每秒
#ani.event\u source.interval=缓慢刷新
类plotApp(tk.tk):
定义初始化(self,*args,**kwargs):
tk.tk.\uuuuu初始化(self,*args,**kwargs)
tk.tk.wm_标题(自,“绘图应用程序”)
容器=tk.框架(自身)
container.pack(side=“top”,fill=“both”,expand=True)
container.grid_rowconfigure(0,权重=1)
container.grid\u column配置(0,权重=1)
菜单栏=传统菜单(容器)
filemenu=tk.Menu(menubar,tearoff=0)
filemenu.add_命令(label=“Exit”,command=quit)
menubar.add_级联(label=“File”,menu=filemenu)
startStop=tk.菜单(菜单栏,tearof=1)
startStop.add_命令(label=“Resume”,command=lambda:toggle_refresh_plot('Resume'))
startStop.add_命令(label=“Freeze”,command=lambda:toggle_refresh_plot('Freeze'))
菜单栏.add_级联(label=“Refresh”,menu=startStop)
tk.tk.config(self,menu=menubar)
self.frames={}#初始化空帧
#建立图形框架
框架=图形(容器、自身)
self.frames[图]=帧
frame.grid(行=0,列=0,sticky=“nsew”)
self.show_框架(图形)
#构建命令框架
frame=命令(容器,s
from datetime import datetime, timedelta
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
from tkinter import ttk
def toggle_refresh_plot(toggle):
global refresh_flag
if toggle == 'resume':
refresh_flag = True
elif toggle == 'freeze':
refresh_flag = False
def animate(i):
print("refresh_flag", refresh_flag)
if refresh_flag:
try:
# query data here
# x, y = my_big_query_command(my_parameter)
x = np.arange(10)
y = np.sqrt(x)
a1 = plt.subplot2grid((1, 2), (0, 0), rowspan=1, colspan=1)
a2 = plt.subplot2grid((1, 2), (0, 1), sharey=a1, rowspan=1, colspan=1)
plt.subplots_adjust(wspace=0.2)
a1.plot(x, y, 'b-')
a2.plot(x, x / (y + 1), 'b-')
print('refreshed: ', datetime.today())
except Exception as e:
print("error message:", str(e))
ani.event_source.interval = slow_refresh # after query slow down pace
else:
ani.event_source.interval = 1000 # every second
# ani.event_source.interval = slow_refresh
class plotApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Plotting App")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
menubar = tk.Menu(container)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=quit)
menubar.add_cascade(label="File", menu=filemenu)
startStop = tk.Menu(menubar, tearoff=1)
startStop.add_command(label="Resume", command=lambda: toggle_refresh_plot('resume'))
startStop.add_command(label="Freeze", command=lambda: toggle_refresh_plot('freeze'))
menubar.add_cascade(label="Refresh", menu=startStop)
tk.Tk.config(self, menu=menubar)
self.frames = {} # initialize empty frames
# build Graph frame
frame = Graph(container, self)
self.frames[Graph] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Graph)
# build Commands frame
frame = Commands(container, self)
self.frames[Commands] = frame
frame.grid(row=0, column=1)
self.show_frame(Commands)
def show_frame(self, frame_name):
frame = self.frames[frame_name]
frame.tkraise()
class Commands(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.parent = parent
side_frame = tk.Frame(self)
side_frame.pack()
Lab1 = tk.Label(side_frame, text="Insert name", anchor=tk.W)
Lab1.grid(row=1, column=0)
def set_entry(self):
global my_parameter
my_parameter = (e1.get())
print("Entry:", my_parameter)
toggle_refresh_plot('resume')
e1 = ttk.Entry(side_frame)
e1.bind("<Return>", set_entry)
e1.grid(row=2, column=0)
class Graph(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
f = plt.figure()
# a1 = f.add_subplot(111)
refresh_flag = False
slow_refresh = 60 * 1000 # refresh plot every 60 sec
my_parameter = '' # initialize as empty
app = plotApp()
ani = animation.FuncAnimation(f, animate, interval=slow_refresh) # update chart every 'interval' milliseconds
app.mainloop()