在 tkinter 中不断更新图形
continuously updating graph in tkinter
我有以下 python 代码(在 PyCharm 中),用于从 Arduino
板上获取读数。读数本身很好。我在代码的 tkinter 部分有以下两个问题:
- 代码一开始就开始从Arduino读取值
已启动,而我想通过单击按钮启动它
('read_data');只要我不按 'read_data' 按钮,
不显示图形,但会读取读数;我可以看到当
我在开始 运行 代码后几秒钟打开图表;
- 当我关闭图
close_plot
时,图 window 确实是
关门了,过一会儿才重新开门。
我认为问题出在Top.after
,因为它在mainloop()
内不断地运行,因此,read_data
功能不断更新。我该如何解决这个问题?
import serial
from tkinter import *
from matplotlib import pyplot as plt
Top = Tk()
ser = serial.Serial('COM3', baudrate=9600, timeout=1)
x = []
y = []
def read_data():
plt.ion()
new_value = ser.readline().decode('ascii')
if new_value == '':
pass
else:
y.append(eval(new_value[:-2]))
x.append(len(y) - 1)
plt.plot(x, y, 'r-')
plt.show()
plt.pause(0.0001)
Top.after(100, read_data)
def close_plot():
plt.close()
global x, y
x = []
y = []
def quit():
Top.destroy()
Button(Top, text='Read', command=read_data).pack()
Button(Top, text='Close plot', command=close_plot).pack()
Button(Top, text='Quit', command=quit).pack()
Top.after(100, read_data)
mainloop()
编辑:按下 read_data
按钮时,我收到以下警告:
C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\backend_bases.py:2445: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented warnings.warn(str, mplDeprecation)
首先,删除行:
Top.after(100, read_data)
像 furas 建议的那样 立即 在 mainloop()
之前。
然后添加 after_cancel
方法以停止每 100 毫秒调用 read_data
,但要使其工作,我们需要将方法内部使用的 after
分配给全局变量第一:
func_id = Top.after(100, read_data)
然后最后在close_plot
中调用after_cancel
:
Top.after_cancel(func_id)
您的代码应完全如下所示:
import serial
from tkinter import *
from matplotlib import pyplot as plt
Top = Tk()
ser = serial.Serial('COM3', baudrate=9600, timeout=1)
x = []
y = []
func_id = None
def read_data():
global func_id
plt.ion()
new_value = ser.readline().decode('ascii')
if new_value == '':
pass
else:
y.append(eval(new_value[:-2]))
x.append(len(y) - 1)
plt.plot(x, y, 'r-')
plt.show()
plt.pause(0.0001)
func_id = Top.after(100, read_data)
def close_plot():
global func_id
#to no longer update the plot
Top.after_cancel(func_id)
plt.close()
global x, y
del x[:]
del y[:]
def quit():
Top.destroy()
Button(Top, text='Read', command=read_data).pack()
Button(Top, text='Close plot', command=close_plot).pack()
Button(Top, text='Quit', command=quit).pack()
mainloop()
我有以下 python 代码(在 PyCharm 中),用于从 Arduino
板上获取读数。读数本身很好。我在代码的 tkinter 部分有以下两个问题:
- 代码一开始就开始从Arduino读取值 已启动,而我想通过单击按钮启动它 ('read_data');只要我不按 'read_data' 按钮, 不显示图形,但会读取读数;我可以看到当 我在开始 运行 代码后几秒钟打开图表;
- 当我关闭图
close_plot
时,图 window 确实是 关门了,过一会儿才重新开门。
我认为问题出在Top.after
,因为它在mainloop()
内不断地运行,因此,read_data
功能不断更新。我该如何解决这个问题?
import serial
from tkinter import *
from matplotlib import pyplot as plt
Top = Tk()
ser = serial.Serial('COM3', baudrate=9600, timeout=1)
x = []
y = []
def read_data():
plt.ion()
new_value = ser.readline().decode('ascii')
if new_value == '':
pass
else:
y.append(eval(new_value[:-2]))
x.append(len(y) - 1)
plt.plot(x, y, 'r-')
plt.show()
plt.pause(0.0001)
Top.after(100, read_data)
def close_plot():
plt.close()
global x, y
x = []
y = []
def quit():
Top.destroy()
Button(Top, text='Read', command=read_data).pack()
Button(Top, text='Close plot', command=close_plot).pack()
Button(Top, text='Quit', command=quit).pack()
Top.after(100, read_data)
mainloop()
编辑:按下 read_data
按钮时,我收到以下警告:
C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\backend_bases.py:2445: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented warnings.warn(str, mplDeprecation)
首先,删除行:
Top.after(100, read_data)
像 furas 建议的那样 立即 在 mainloop()
之前。
然后添加 after_cancel
方法以停止每 100 毫秒调用 read_data
,但要使其工作,我们需要将方法内部使用的 after
分配给全局变量第一:
func_id = Top.after(100, read_data)
然后最后在close_plot
中调用after_cancel
:
Top.after_cancel(func_id)
您的代码应完全如下所示:
import serial
from tkinter import *
from matplotlib import pyplot as plt
Top = Tk()
ser = serial.Serial('COM3', baudrate=9600, timeout=1)
x = []
y = []
func_id = None
def read_data():
global func_id
plt.ion()
new_value = ser.readline().decode('ascii')
if new_value == '':
pass
else:
y.append(eval(new_value[:-2]))
x.append(len(y) - 1)
plt.plot(x, y, 'r-')
plt.show()
plt.pause(0.0001)
func_id = Top.after(100, read_data)
def close_plot():
global func_id
#to no longer update the plot
Top.after_cancel(func_id)
plt.close()
global x, y
del x[:]
del y[:]
def quit():
Top.destroy()
Button(Top, text='Read', command=read_data).pack()
Button(Top, text='Close plot', command=close_plot).pack()
Button(Top, text='Quit', command=quit).pack()
mainloop()