在tkinter中不断更新图形

时间:2017-12-25 16:01:41

标签: python tkinter pyserial

我有以下python代码(在PyCharm中),我用来从Arduino板读取数据。读数本身很好。我在代码的tkinter部分遇到以下两个问题:

  1. 代码一旦开始从Arduino开始读取值 已启动,而我想通过单击按钮启动此功能 ('的read_data&#39);只要我不按“阅读数据”即可。按钮, 图表不显示,但读数;我什么时候能看到 我在开始运行代码几秒后打开图表;
  2. 当我关闭地块close_plot时,确实是图形窗口 关闭,不久之后才重新开放。
  3. 我认为问题在于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)
    

1 个答案:

答案 0 :(得分:1)

首先,删除该行:

Top.after(100, read_data)

mainloop() furas建议之前立即

然后添加after_cancel方法以每100毫秒停止调用read_data,但为了实现这一点,我们需要首先将方法内部使用的after分配给全局变量:

func_id = Top.after(100, read_data)

然后最终在after_cancel中致电close_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()