Cai*_* S. 5 c++ python tk-toolkit tkinter python-3.x
我正在将一个程序(VMD,视觉分子动力学)移植到 Python 3.x,该程序是用 C++ 编写的,并且嵌入了 Python 和 TCL 解释器。其大部分 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 Tkinter\n"
"while Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n"
" pass\n"
);
in_tk = 0;
if (rc) {
return 1; // success
}
// give up
have_tkinter = 0;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然而该函数tkinter.dooneevent已从 Python 3 中删除,我找不到它的替代品。我尝试调用低级,Tcl_DoOneEvent(TCL_DONT_WAIT)但是当我动态创建一个新窗口时,我最终导致 Python 解释器崩溃并出现错误Fatal Python error: PyEval_RestoreThread: NULL tstate。
tkinter woes when porting 2.x code to 3.x, 'tkinter' module attribute does not believe中的答案没有帮助,因为我没有用户可能创建的所有窗口的列表。
在这种情况下,有人对如何刷新 TK 事件有任何建议吗?它可以在 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.
Run Code Online (Sandbox Code Playgroud)
现在,我不知道如何准确地将其转换为您的代码 - 您是否有可以访问的根 Tk 对象dooneevent?我对 python 2 tkinter 一点也不熟悉,所以我不知道我的代码映射到你的代码的准确程度。然而,当我做一些与你非常相似的事情时,我发现了这一点——试图将tkinter事件循环集成到asyncio事件循环中。我能够创建一个在循环中调用此方法的协程,每次都会产生(并偶尔休眠),以便 GUI 保持响应,而不会阻塞 asyncio 事件循环tkinter._tkinter.create()。
@asyncio.coroutine
def update_root(root):
while root.tk.dooneevent(tkinter._tkinter.DONT_WAIT):
yield
Run Code Online (Sandbox Code Playgroud)
编辑:我刚刚读到你关于没有小部件的评论。我知道该root.tk对象是tkinter._tkinter.TkappType通过调用创建的实例tkinter._tkinter.create,并且我不认为它是全局的。我很确定它是核心 Tcl 解释器。您也许可以通过调用 来创建自己的create。虽然没有记录,但您可以查看它的用法tkinter.Tk.__init__
| 归档时间: |
|
| 查看次数: |
2648 次 |
| 最近记录: |