Reputation: 205
I have the following python code (in PyCharm) that I use to take readings from an Arduino
board. The readings themselves are fine. I have the two following problems with the tkinter part of the code:
close_plot
, the graph window is indeed
closed, only to be re-opened a short while later.I think the problem lies in Top.after
as it is continuously run within the mainloop()
and, therefore, the read_data
function is continuously updated. How can I get around this?
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()
Edit: when pressing the read_data
button, I get the following warning:
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)
Upvotes: 1
Views: 3660
Reputation: 15335
First, remove the line:
Top.after(100, read_data)
that comes immediately before mainloop()
like furas suggested.
Then add after_cancel
method to stop calling read_data
every 100 ms, but for that to work, we need to be assigning after
we use inside the method to a global variable first:
func_id = Top.after(100, read_data)
and then finally call after_cancel
in close_plot
:
Top.after_cancel(func_id)
Your code should be exactly like below:
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()
Upvotes: 1