我正在尝试在tkinter中做一个简单的计数计时器。计时器启动并计数,但我不知道如何停止它。我正在尝试使用threading.event,但我错过了一些东西,我就是不能得到正确的代码。
运行下面的代码会得到“attributeError:“MainFrame”对象没有属性“x”“。
#!/usr/bin/python3.9
import tkinter as tk
from tkinter import ttk
from threading import Thread
from threading import Event
import time
class Timer(Thread):
def __init__(self, count):
super().__init__()
self.stop_threads = Event()
self.entry1 = None
self.count = count
def run(self):
while True:
if self.stop_threads.is_set():
break;
else:
mins, secs = divmod(self.count, 60)
timeformat = '{:02d}:{:02d}'.format(mins, secs)
#print(timeformat, end='\r')
self.entry1 = timeformat
time.sleep(1)
self.count += 1
def stop_threads(self):
self.stop_threads.set()
class MainFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
### TOP BUTTON ROW
self.frame1=ttk.Frame(self, padding = (0, 50, 0, 30), ) ## LH padding, TOP padding, RH padding, BOTTOM padding
self.frame1.pack(fill="x", ipadx=0, ipady=0, padx=0, pady=0, expand=False)
### TOP TEXT BOX
self.frame2=ttk.Frame(self, padding = (0, 0, 0, 0), ) ## LH padding, TOP padding, RH padding, BOTTOM padding
self.frame2.pack(fill="x", ipadx=0, ipady=0, padx=0, pady=0, expand=False)
### MID TEXT BOX
self.frame3=ttk.Frame(self, padding = (40, 20, 40, 0))
self.frame3.pack(fill="x", ipadx=0, ipady=0, padx=0, pady=0, expand=False)
# show the frame on the container
self.pack()
### START BUTTON
self.button1=tk.Button(self.frame1, text='START')
self.button1['command'] = self.delay
self.button1.pack(expand=True, padx=0, pady=0, ipadx=0, ipady=0, side="left")
### STOP BUTTON
self.button2=tk.Button(self.frame1, text='STOP')
self.button2['command'] = self.stop
self.button2.pack(expand=True, padx=0, pady=0, ipadx=0, ipady=0, side="right")
### TIMER DISPLAY LABEL
self.entry1_label=tk.Label(self.frame2 , text='TIMER', bg="white", fg="blue")
self.entry1_label.pack(padx=10, pady=0, ipadx=0, ipady=0, expand=False, side="left")
### TIMER DISPLAY
self.entry1_var = tk.StringVar()
self.entry1=tk.Entry(self.frame2, textvariable="entry6_var", width=10, justify="center")
self.entry1.pack(padx=0, pady=0, ipadx=0, ipady=4, expand=False, side="left")
### MSG DISPLAY
self.text1 = tk.Text(self.frame3, height=1)
self.text1.pack(expand=False, padx=0, pady=0, ipadx=0, ipady=0, side="left")
def delay(self):
event = Event()
self.button1['state'] = tk.DISABLED
timer_thread=Timer(0)
timer_thread.start()
self.monitor(timer_thread)
def stop(self):
x = Timer(0)
x.stop_threads()
self.text1.insert("end", "stopping")
def monitor(self,thread):
if thread.is_alive():
self.entry1.delete('0', tk.END)
self.entry1.insert("end", thread.entry1)
#check the thread every 100ms
self.after(100,lambda:self.monitor(thread))
else:
self.text1.insert("end", "thread is stopped")
self.button1['state']=tk.NORMAL
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.geometry("600x300")
self.option_add('*Font', 'Helvetica 9') ## drop down menu font & size / https://coderslegacy.com/python/problem-solving/change-font-in-tkinter/
self.configure(bg="white") ## bottom background colour
self.resizable(False, False)
self.title("TEST TIMER")
### frame style
f = ttk.Style()
f.configure('TFrame', background='white') ## background colour
#def exit(self):
#self.destroy()
if __name__ == "__main__":
app = App()
frame = MainFrame(app)
app.mainloop()
1条答案
按热度按时间lskq00tm1#
移除
从
Timer
开始,尝试使用x.stop_threads.set()
而不是x.stop_threads()
问题的一部分在于你的
Timer.__init__()
说self.stop_threads = Event()
,但是def stop_threads(self)
重写了它,因为它有相同的名字。最后,因为你用self.stop_threads
示例化了Event
类,所以你不需要这个方法。但是,您可能会遇到一些麻烦,因为
MainFrame.delay
和MainFrame.stop
方法都在示例化Timer
,并且这些计时器将具有单独的stopEvent
。您还可以稍微修改一下
run
方法:除此之外,在tkinter旁边使用
Thread
和sleep
时我会很小心,如果你想要一个倒计时器,你最好使用tkinter.after
,因为它不会导致你的应用挂起。如果你想使用
after
,你可以完全删除线程。