从GUI启动和停止线程

时间:2018-12-15 16:10:47

标签: python python-3.x tkinter

我目前正在开发带有GUI的程序,以从传感器收集数据并在GUI中可视化它。 来自传感器的数据存储在列表中,以供进一步计算。

我当前正在尝试做的是在新线程中启动日志记录过程。 这应该可以防止GUI冻结。

我当前的代码:

import tkinter as tk
import time
import threading

class GUI:
    def __init__(self, tk_object):
        self.gui = tk_object
        self.gui.title("Logger") 
        self.gui.resizable(width=True, height=True)

        self.testlabel = tk.Label(self.gui, text="Recording in process")
        self.testlabel.grid(row = 7, column = 0)
        self.testlabel.config(bg='white')

        btn1 = tk.Button(master, text="Start Recording", width=16, height=5, command=lambda: self.start_functions())
        btn1.grid(row=2,column=0)
        btn2 = tk.Button(master, text="Stop Recording", width=16, height=5, command=lambda: self.stop_functions())
        btn2.grid(row=3,column=0)

    def start_functions(self):
        """Calls the method get_sample in a new thread and changes the bg-color of the label to red""" 
        Thread_1 = threading.Thread(target=self.get_sample(), name='Thread1')        
        Thread_1.start()
        self.testlabel.config(bg='red') 

    def stop_functions(self):
        """Stops all active threads and changes bg-color of the label back to white""" 
        #stop_threads = threading.Event()
        #stop_threads.set()
        threading.Event().set()
        self.testlabel.config(bg='white')            

    def get_sample(self):
        """get data and append it to a list"""
        while not threading.Event().is_set():
            time.sleep(1)
            res_cel.append(res_cel[-1]+1)
            x_value.append(x_value[-1]+1)
        print(res_cel)
        print(x_value) 


master = tk.Tk()
master_object = GUI(master)
master.mainloop()

当前,get_sample方法包含一个占位符。 我试图通过get_sample处理程序停止Thread1(运行Event()方法的地方)。

while not threading.Event().is_set():

这似乎无法正常工作。 有更好的方法可以做到这一点吗? 在采用这种方法之前,我尝试使用class处理线程(这是在stackoverflow上找到的,但是对不起,我似乎再也找不到它了):

class Controller(object):

def __init__(self):
    self.thread1 = None
    self.stop_threads = Event()

def run(self):
    .. do somehting

并通过以下方式启动/停止线程:

def starting_thread(self):
    self.stop_threads.clear()
    self.thread1 = Thread(target = self.run)
    self.thread1.start()

def stopping_thread(self):
    self.stop_threads.set()
    self.thread1 = None

注意:这些函数在Controller类中。 使用此解决方案,我无法更改GUI类中的标签背景颜色,因为它不知道它所引用的对象。

我对python编程还很陌生,所以如果有人可以向我解释我在这里缺少的内容,我会很高兴。

谢谢 xSaturn

1 个答案:

答案 0 :(得分:1)

您最好创建自己的Thread对象,并带有一种方法来停止它。当线程使用其run方法时,它将停止运行。看下面的例子

import time
import tkinter as tk
from threading import Thread

class MyThread(Thread):
    thread_running = False

    def run(self):
        k = 0
        self.thread_running = True
        while self.thread_running:
            print(k)
            k +=1
            time.sleep(1)
        print("thread ended")

    def stop(self):
        self.thread_running = False


class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        self.thread = None

        tk.Button(self, text="launch thread", command=self.launch_thread)\
            .grid(row=1, column=0)
        tk.Button(self, text="stop thread", command=self.stop_thread)\
            .grid(row=2, column=0)

    def launch_thread(self):
        if self.thread:
            print("thread already launched")
        else:
            print("thread launched")
            self.thread = MyThread()
            self.thread.start()


    def stop_thread(self):
        if self.thread:
            self.thread.stop()
            self.thread = None
        else:
            print("no thread running")

if __name__ == '__main__':
    win = Window()
    win.mainloop()

有关更多信息,请参阅本主题。 Is there any way to kill a Thread?