Substitute for tkinter.dooneevent
Substitute for tkinter.dooneevent
我正在移植一个程序(VMD,Visual Molecular Dynamics),它是用C++编写的,嵌入了Python和TCL解释器,到Python 3.x。它的大部分UI都是使用TCL/TK框架和OpenGl硬编码的,因此UI刷新是手动完成的。当Python解释器运行时,可以使用Tkinter动态创建新窗口,甚至可以向主UI添加新菜单。在这种情况下,所有 TK 事件都通过定期调用 Python 端的一些代码来刷新(见下文)。这可确保所有更新都是线程安全的,并且不会破坏解释器。
int PythonTextInterp::doTkUpdate() {
// Don't recursively call into dooneevent - it makes Tkinter crash for
// some infathomable reason.
if (in_tk) return 0;
if (have_tkinter) {
in_tk = 1;
int rc = evalString(
"import Tkintern"
"while Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):n"
" passn"
);
in_tk = 0;
if (rc) {
return 1; // success
}
// give up
have_tkinter = 0;
}
return 0;
}
但是,tkinter.dooneevent
函数已从Python 3中删除,我找不到它的替代品。我尝试调用低级Tcl_DoOneEvent(TCL_DONT_WAIT)
但是当我动态创建一个新窗口时,我最终使Python解释器崩溃,错误Fatal Python error: PyEval_RestoreThread: NULL tstate
。
将 2.x 代码移植到 3.x 时,tkinter 困境中的答案,"tkinter"模块属性不存在,这无济于事,因为我没有用户可能创建的所有窗口的列表。
在这种情况下,有没有人对如何刷新传统知识事件有任何建议?它可以在Python端或C++。
提前致谢
看起来这是等效的:
root = tkinter.Tk()
# Here's your event handler. Put it in a loop somewhere.
root.tk.dooneevent(tkinter._tkinter.DONT_WAIT)
# I don't know if it's possible to access this method without a Tk object.
现在,我不知道如何准确地将其转换为您的代码 - 您是否有一个根 Tk 对象可以访问dooneevent
?我对python 2 tkinter一点也不熟悉,所以我不知道我的代码映射到你的代码的确切程度。但是,当我做与您非常相似的事情时,我发现了这一点 - 尝试将tkinter
事件循环集成到asyncio
事件循环中。我能够创建一个在循环中调用此方法的协程,每次都产生(并且偶尔休眠),以便 GUI 保持响应,而不会阻塞带有 tkinter._tkinter.create()
的异步事件循环。
@asyncio.coroutine
def update_root(root):
while root.tk.dooneevent(tkinter._tkinter.DONT_WAIT):
yield
编辑:我刚刚阅读了您关于没有小部件的评论。我知道root.tk
对象是通过调用tkinter._tkinter.create
创建的tkinter._tkinter.TkappType
实例,我认为它不是全局的。我很确定它是核心的Tcl解释器。您可以通过调用 create
来创建自己的 。虽然它没有记录在案,但您可以在tkinter.Tk.__init__
中查看它的用法