我在 Python 中冻结应用程序时遇到问题。我使用 tkinter 库制作了一些应用程序。当我使用“发送”按钮时,它会调用持续 3 分钟的功能,并在这 3 分钟内冻结应用程序...我想“实时”查看此功能的所有日志。我不能等 3 分钟然后获取所有日志。
下面是我的代码示例:
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
import time
class Frames:
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def button_frame(self, win):
# Button Frame
butt_frame = ttk.LabelFrame(win, text="Button")
butt_frame.grid(column=0, row=0, sticky='NWS')
def _send_button():
for i in range(10):
self.write_text_console("{0}\n".format(i))
time.sleep(0.5)
# Send Button
ttk.Label(butt_frame, text=" ").grid(column=0, row=8)
button = tk.Button(butt_frame, text="Send", command=_send_button, foreground='black')
button.grid(column=0, row=13, sticky=tk.EW)
def scrolled_text_widget(self, win):
ttk.Label(win, text=" ").grid(column=0, row=1)
ttk.Label(win, text="Console Output:").grid(column=0, row=2, sticky=tk.W)
self.scr = scrolledtext.ScrolledText(win, width=100, height=10, wrap=tk.WORD, state="disabled")
self.scr.grid(column=0, row=3, columnspan=5)
def write_text_console(self, string, color="black", tag="console"):
self.scr.configure(state='normal')
self.scr.insert('end', string, tag)
self.scr.tag_config(tag, foreground=color)
self.scr.configure(state='disabled')
self.scr.see("end")
win = tk.Tk()
win.geometry("845x300")
win.resizable(0, 0)
frames = Frames()
main = frames.main_frame(win)
frames.button_frame(main)
frames.scrolled_text_widget(main)
win.mainloop()
这个例子显示了我的问题。当您单击“发送”按钮时,它会将应用程序冻结 5 秒。但我需要在循环期间查看日志。
如何解决?
Tkinter 在您的主线程中运行循环,这就是您的应用程序在您单击按钮时冻结的原因。解决方案是创建一个新线程。
1-你必须导入线程
import threading
2- 在 _send_button() 函数中启动一个新线程。应该是这样的。
def _send_button():
def click_button():
for i in range(10):
self.write_text_console("{0}\n".format(i))
time.sleep(0.5)
threading.Thread(target=click_button).start()
要冻结按钮,请在特定按钮小部件中添加
state= DISABLED
。
from tkinter import *
#Create an instance of tkiner frame
root= Tk()
#Define the geometry of the function
root.geometry("400x250")
Button(root, text="OK", state= DISABLED).pack(pady=20)
root.mainloop()
在 Tkinter 中,GUI 在应用程序代码(包括事件处理程序)的同一线程中运行。而且由于它是单线程的,事件处理程序必须快速响应,否则它们将阻止其他事件的处理。
您应该避免在事件处理程序中进行长时间运行的计算,使用计时器将它们分成更小的部分或在另一个线程中运行.
也就是说,这是解决您问题的简单解决方案。
def _send_button():
for i in range(10):
self.write_text_console("{0}\n".format(i))
win.update_idletasks()
time.sleep(0.5)