微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 tkinter 中的按钮开始和停止线程中的重复任务

如何解决从 tkinter 中的按钮开始和停止线程中的重复任务

我想从 tkinter 制作的 GUI 开始一个任务,它应该每 10 秒运行一次。 GUI 有一个开始按钮和一个停止按钮,以及一个停止线程的事件。 我正在使用调度模块和线程以避免冻结 GUI。

from functools import partial
import tkinter as tk
from threading import Thread,Event,Lock
import schedule
import time
import os


class GUI():
    def __init__(self,master):
        self.master = master
        self.frame = tk.Frame(self.master)
        
        self.button1 = tk.Button(text='Start',command=partial(run_threaded,experiment),width=20,height=2,bg="gray",fg="black")
        self.button1.pack()
        self.button2 = tk.Button(text='Stop',command=stop_button,fg="black")
        self.button2.pack()
    
def job():
    print("Task started") 
    print("Task completed") 
        
def experiment():
    schedule.every(10).seconds.do(job)
    while 1:
        schedule.run_pending()
    
def run_threaded(job_func):
    job_thread = Thread(target=job_func)
    job_thread.start()
    if stop_threads.is_set():
        job_thread.join()
        job_thread = None

def start_button():
    run_threaded(experiment)
    
def stop_button():
    global stop_threads
    stop_threads.set()

def main():
    global stop_threads
    thread1=None
    stop_threads = Event()
    root = tk.Tk()
    app = GUI(root)
    root.mainloop()

if __name__ == '__main__':
    main()

任务在 10 秒后开始并定期重复,但停止按钮不起作用,我希望该过程立即开始,没有最初的延迟。

此外,每隔一次我运行它时,任务就会启动,但 GUI 不会出现。

有没有更好的方法来实现这一点?

解决方法

尝试这样的事情:

import tkinter as tk
from time import sleep
from functools import partial
from threading import Thread

running_job = False


def job():
    print("Task started") 
    print("Task completed") 

def experiment():
    while running_job:
        job()
        # I changed it to 1 sec to make it easier to test
        sleep(1)


class GUI:
    def __init__(self,master):
        self.master = master
        self.frame = tk.Frame(self.master)

        command = partial(run_threaded,experiment)
        self.button1 = tk.Button(text="Start",command=command)
        self.button1.pack()
        self.button2 = tk.Button(text="Stop",command=stop_button)
        self.button2.pack()


def run_threaded(job_func):
    global running_job
    running_job = True
    job_thread = Thread(target=job_func,daemon=True)
    job_thread.start()

def stop_button():
    global running_job
    running_job = False

if __name__ == "__main__":
    root = tk.Tk()
    app = GUI(root)
    root.mainloop()

它使用一个名为 running_job 的全局变量。当 running_jobTrue 时,while 内的 experiment 循环可以运行。当转向 False 时,experiment 停止。这种方法的问题在于,如果您在 tkinter 函数中使用 job 小部件/变量,tkinter 可能会崩溃。

另一种方法是使用 .after 脚本,但要使其正常工作,job 函数的执行时间不应太长。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。