私は基本的に、シリアルポートからデータを取得し、Tkinter を使用して作成された GUI に表示されるグラフにプロットすることをシミュレートしています。入力シリアル データは、正弦関数を計算し、サイズ 100 のキューに値を追加する単純な while ループによってシミュレートされます。プログラムのデータ生成部分は、DataThreadという名前のクラスの下に記述されます。
import Tkinter as tk
import numpy as np
import matplotlib as plt
from collections import deque
import threading
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from time import sleep
class DataThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.ISCONNECTED = 1
self.d = deque(maxlen=100)
def run(self):
t = 1
while True:
wave = np.sin(2*np.pi*100*t*0.001)
self.d.append(wave)
print(wave)
t = t+1
sleep(1)
if self.ISCONNECTED == 0:
break
他のクラスは GUI を生成し、DataThreadクラスのインスタンスを作成し、関数start_dを呼び出すと、データを生成するスレッドが開始されます。停止ボタンを押してスレッドを停止したいのですが、スレッドの停止方法がわかりません。
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W))
self.fig = Figure()
self.ax_1 = self.fig.add_subplot(111)
self.createWidgets()
self.a = DataThread()
def createWidgets(self):
self.frame = tk.Frame(borderwidth=5,
relief="sunken", width=300, height=20)
self.frame.grid(column=0, row=0, columnspan=10, rowspan=4,
sticky=(tk.N, tk.S, tk.E, tk.W))
self.frame.rowconfigure(0, weight=1)
self.frame.columnconfigure(0, weight=1)
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.canvas.get_tk_widget().grid()
self.canvas.show()
self.namelbl = tk.Label(text="Start DAQ")
self.namelbl.grid(column=10, row=0, columnspan=2,
sticky=(tk.S, tk.W), padx=5)
self.start = tk.Button( text='Start',
command=self.quit)
self.start.grid(column=10, row=1,sticky=tk.N+tk.S+tk.E+tk.W)
self.stop = tk.Button( text='Stop',
command=self.stop_serial)
self.stop.grid(column=11, row=1,sticky=tk.N+tk.S+tk.E+tk.W)
def start_d(self):
self.a.ISCONNECTED=1
self.a.start()
def readSensor(self):
data2plot = self.a.d
self.ax_1.plot(range(data2plot),data2plot)
self.root.update()
self.root.after(527, self.readSensor)
def stop_serial(self):
self.a.ISCONNECTED=0
def run(self):
self.mainloop()
そして、単純に GUI を実行する最後の部分
if __name__ == "__main__":
Application().run()
次の質問のコードに基づいています:シリアル データに基づいて Tkinter ウィンドウを動的に更新する 違いは、GUI スレッドとデータ スレッドの両方が同時に作成されることですが、私の場合は、スタートボタンを押したときだけ糸を通す。