这可能有点晚了,但无论如何......
我自己的研究发现了在 event_generate 调用中添加 'when="tail"' 的建议,以确保事件正确排队。如果你不这样做,Tk 事件规则可能会对事件队列做一些奇怪的事情。Tkinter 中没有(还没有?)记录。
即便如此,我自己的研究(和经验!)也发现 Tkinter 从根本上不是线程安全的。这意味着你不能保证在它自己的线程之外用 Tkinter 做任何事情都会奏效。当然,最安全的方法是生成事件,但即使这样也会经常抛出异常,这表明 Tkinter 内部对于添加事件不是线程安全的。通常这些异常是可以生存的,所以我使用重试来再次破解,这主要是有效的。
retries = 3
done = False
unknownException = False
while (retries != 0) and (not done) and (not unknownException):
try:
self._applicationWindow.event_generate("<<MyNewEvent>>", when="tail")
done = True
except Tk.TclError as err:
if "application has been destroyed" in err.message:
# If application is destroyed, this event is not needed
done = True
elif ("expected boolean value but got" in err.message) or ("bad option" in err.message):
# These are bugs in Tk/Tcl/Tkinter, not in our code. They seem to be uncommon,
# and seem to be survivable. Hopefully retrying will have the system in a
# slightly different state where this doesn't happen next time.
print "Tkinter/Tk/Tcl error, retry " + str(retries)
retries = retries - 1
else:
unknownException = True
except:
unknownException = True
# Unlock afterwards
self._eventLock.release()
if not done:
# If retries haven't helped or we have an exception which isn't one we know about,
# then pass the exception up the tree.
raise
一个非线程安全的 UI 层是一回事——我猜它简化了设计,所以它几乎可以接受。但是,非线程安全的事件队列应该是您的编程入门课程中的失败等级。如果您得出结论认为 Tkinter 已损坏并且不应该用于任何实际应用程序 - 加入俱乐部。就我而言,任何 Tkinter 问题的正确解决方法是使用另一个适合目的的 UI 层。:/
PS。我正在使用 Python 2.7.6。Python 3 上的 YMMV。