【发布时间】:2022-01-11 16:25:30
【问题描述】:
我是 tkinter 的新手。当我尝试创建诸如for i in range(100) 之类的循环时,GUI '崩溃',这意味着我无法操作 GUI,直到循环结束(即使我没有在文本中插入任何内容)。在我检查了一些信息后,我尝试了线程。它确实有效。但是……
from tkinter import *
import time
from threading import Thread
class Application(Frame):
def __init__(self):
self.root = Tk()
self.root.title('tkinter')
self.root.geometry('400x300+400+100')
self.createWidget()
self.root.mainloop()
def createWidget(self):
self.text = Text(self.root, width=40, height=15, relief=SOLID, borderwidth=1)
self.text.grid(row=0, column=0)
self.button = Button(self.root, text="click", relief=SOLID, borderwidth=1, command=self.button_click)
self.button.grid(row=1, column=0)
pass
def button_click(self):
t1 = Thread(target=self.loop)
t1.start()
def loop(self):
for i in range(100):
self.text.insert(END, chars=str(i)+'\n')
time.sleep(1)
self.root.update()
self.text.see(END)
if __name__=="__main__":
Application()
但是每次遇到循环都不可能使用线程(太难了,在某些情况下必须顺序执行)。有什么有用/简单的方法来处理它?
【问题讨论】:
-
尝试删除
time.sleep(1)。如果您需要减慢文本插入速度,请尝试使用after。 -
您不能在事件处理程序中运行循环。与所有 GUI 框架一样,Tkinter 是事件驱动的。当您创建或修改窗口时,不会绘制任何内容。所做的只是向控件发送消息。当您的代码返回主循环时,即是获取和处理消息的时间。您的处理程序必须快速运行并返回,以便处理消息。因此,您必须使用
root.after在一秒钟内请求回调。您在那一秒钟内进行更新,再次调用root.after,然后返回。 -
此外,所有 Tkinter 更新必须在主线程中完成。您不能在辅助线程中进行 UI 更新。所有的 GUI 框架也是如此。