所以假设我有一个Tkinter GUI,它显示一个RUN按钮,一个STOP按钮和一个ScrolledText
小部件。按RUN按钮将调用包含多个log.info()
呼叫的功能。文本小部件应该显示那些日志。我希望这些日志在发生时能够实时显示,所以我尝试将该功能作为线程运行,并希望按下STOP按钮终止该功能。这就是我现在所拥有的:
我的代码:
import tkinter as tk
import logging
import tkinter.scrolledtext as tkst
import threading
class TextHandler(logging.Handler):
"""This class allows you to log to a Tkinter Text or ScrolledText widget"""
def __init__(self, text):
# run the regular Handler __init__
logging.Handler.__init__(self)
# Store a reference to the Text it will log to
self.text = text
def emit(self, record):
msg = self.format(record)
def append():
self.text.configure(state='normal')
self.text.insert(tk.END, msg + '\n')
self.text.configure(state='disabled')
# Autoscroll to the bottom
self.text.yview(tk.END)
# This is necessary because we can't modify the Text from other threads
self.text.after(0, append)
def setup_logger(logger_name, log_file, level=logging.INFO):
l = logging.getLogger(logger_name)
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
if path.exists(log_file) == False:
fileHandler = logging.FileHandler(log_file, mode='w')
else:
fileHandler = logging.FileHandler(log_file, mode='a')
fileHandler.setFormatter(formatter)
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)
l.setLevel(level)
l.addHandler(fileHandler)
l.addHandler(streamHandler)
setup_logger('logA', 'HeresTheLog.log')
log = logging.getLogger('logA')
def threadding():
app.running = True;
newthread = threading.Thread(target= function)
newthread.start()
def function():
log.info("starts")
(do things)
log.info("ends")
def stop():
app.running = False;
class myApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self, width=768, height=576, bg="")
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.running = True
self.frames = {}
self.show_frame(StartPage)
self.update_idletasks()
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
button2 = ttk.Button(self, text="FUNCTION",
command= function
)
button2.pack(pady=10)
textLog = tkst.ScrolledText(self, state="disabled")
textLog.pack()
text_handler = TextHandler(textLog)
log.addHandler(text_handler)
stopbutton = ttk.Button(self, text = "STOP!", command = stop)
stopbutton.pack()
app = myApp()
app.mainloop()
基本上,我正在尝试使用app.running
来控制线程,但这似乎不起作用。我知道你不能真正杀死线程。所以我想知道更好的方法是什么?也许使用多进程而不是线程,以便我们可以杀死它来阻止它?有人可以详细说明这个想法吗?