Python tkinter中的连续更新图
我有以下python代码(在PyCharm中),用于从Python tkinter中的连续更新图,python,tkinter,pyserial,Python,Tkinter,Pyserial,我有以下python代码(在PyCharm中),用于从Arduino板读取数据。读数本身很好。我对代码的tkinter部分有以下两个问题: 代码一启动就开始从Arduino读取值 已启动,而我希望通过单击按钮启动此操作 (“读取数据”);只要我不按“读取数据”按钮 不显示图形,但读取读数;我可以看到,当 我在开始运行代码几秒钟后打开图形 当我关闭绘图close\u plot时,图形窗口确实处于关闭状态 已关闭,但不久后将重新打开 我认为问题在于Top.after,因为它在mainloop()中连
Arduino
板读取数据。读数本身很好。我对代码的tkinter部分有以下两个问题:
close\u plot
时,图形窗口确实处于关闭状态
已关闭,但不久后将重新打开Top.after
,因为它在mainloop()
中连续运行,因此,read\u 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)
它紧跟在mainloop()之前,就像建议的那样
然后添加after\u cancel
方法停止调用read\u data
每100毫秒一次,但要使其起作用,我们需要在方法内部使用的之后首先将赋值给全局变量:
func_id = Top.after(100, read_data)
然后在close\u plot
中取消后调用:
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()
1.移除Top.after(100,读取数据)
beforemainloop()
-它在程序启动后100毫秒开始读取。顺便说一下:读取。我们仅将“大写名称”用于类名称,如按钮
、Tk
或序列
,但不用于Top
等变量。它使代码更具可读性。即使是Stackoverflow
也知道这条规则,并对类使用浅蓝色。@furas:恐怕你的建议没有帮助,代码一运行就开始阅读。你是否删除了正确的after()
-beforemainloop()
。如果您仍然有问题,那么可能您使用了与问题中显示的不同的代码-即,您可能在command=read_data()
中使用了()
,请尝试在没有PyCharm的情况下运行它-可能PyCharm存在一些问题。或者问题是Anaconda-我只使用标准Python安装进行了测试,没有得到错误“MatplotlibDeprecationWarning”
。我会在()后面加上
externalif/else
所以它会一直读-但我不能测试它。顺便说一句:我尝试在Linux上使用socat
创建假串行端口来测试它-就像在回答中一样,我感谢你的帮助,但我无法让它工作,即使我复制了你的代码。这些错误重复出现。此外,我还收到以下警告:MatplotlibDeprecationWarning:在实现此GUI特定的函数之前使用默认事件循环警告。warn(str,mpldprecation)@DenGor请将导致该错误的MCVE代码段附加到您的问题中,并发布完整的错误消息。@DenGor在此处更新了答案,现在它应该可以工作了。