从 tkinter 中的按钮开始和停止线程中的重复任务
Start and stop a repeating task in a thread from a button in 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, width=20,height=2,bg="gray",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_job
为 True
时,experiment
中的 while
循环可以 运行。转为False
时,experiment
停止。这种方法的问题是,如果您在 job
函数中使用 tkinter
widgets/variables,tkinter 可能会崩溃。
另一种方法是使用 .after
脚本来代替,但要使其正常工作,job
函数的执行时间不会太长。
我想从 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, width=20,height=2,bg="gray",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_job
为 True
时,experiment
中的 while
循环可以 运行。转为False
时,experiment
停止。这种方法的问题是,如果您在 job
函数中使用 tkinter
widgets/variables,tkinter 可能会崩溃。
另一种方法是使用 .after
脚本来代替,但要使其正常工作,job
函数的执行时间不会太长。