如何阻止直到tkinter事件可以处理

2024-04-26 02:53:23 发布

您现在位置:Python中文网/ 问答频道 /正文

编辑:下面可能的解决方案,谁能确认?

我在一个线程中运行tkinter,并试图使用this answer中描述的event_generate技术来控制其他线程的行为。显然,一旦我启动了一个线程,该线程设置了一个tkinter.Tk实例并启动了它的mainloop,那么在尝试生成事件之前,有必要阻塞直到mainloop已经启动。我尝试的方法如下(Python3.2代码):

import tkinter
import threading

mainloop_started = threading.Event()

def tkinter_thread_stuff():
    global root
    root = tkinter.Tk()

    #[code that binds events with root.bind]

    root.after(0, mainloop_started.set)
    root.mainloop()

th = threading.Thread(target=tkinter_thread_stuff)
th.start()

mainloop_started.wait()

#[code that sends events to root with event_generate]

换句话说,我使用after使tkinter主循环设置名为threading.Eventthreading.Event,事件生成代码从阻塞开始,直到设置了这个事件。然而,这似乎会导致竞争条件-有时在mainloop_started.wait()之后快速生成的事件永远不会被tkinter处理。如果我在after调用中设置了一个时间延迟(例如root.after(1000, mainloop_started.set)),则不会发生这种情况,因此看起来在tkinter调用after回调的点和它能够接收事件的点之间有一段时间。在tkinter可以接收事件之前,有人知道正确的阻塞方式吗?在

PS:在这样的线程中运行tkinter主循环安全吗?我知道我不能直接干涉来自其他线程的根或其他tkinter内容,但除此之外,一切似乎都正常工作。我看到一些网站说tkinter只能在主线程中运行。在

编辑:我想我有一个解决方案-用after_idle代替{}。这似乎可以确保在mainloop准备好处理事件之前不会调用回调,但是有人可以确认这一点吗?总之,如果您不能保证调用回调时tkinter将被完全设置,after的意义何在(除非在另一个事件处理程序中调用了after)?在

一个具体的例子,说明在这种情况下使用after和{}的效果,如果有人想玩玩的话:

^{pr2}$

Tags: 代码event编辑tkinter事件root解决方案线程