在tkinter中不断更新图形

问题描述 投票:1回答:1

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

  1. 代码一旦启动就开始从Arduino中读取值,而我想在按下按钮时启动它('read_data');只要我没有按下'read_data'按钮,就不会显示图表,而是会读取读数;我可以看到,当我开始运行代码几秒钟后打开图表时;
  2. 当我关闭情节close_plot时,图形窗口确实关闭,只是稍后重新打开。

我认为问题在于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)
python tkinter pyserial
1个回答
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()
© www.soinside.com 2019 - 2024. All rights reserved.