Substitute for tkinter.dooneevent

Substitute for tkinter.dooneevent

本文关键字:dooneevent tkinter for Substitute      更新时间:2023-10-16

我正在移植一个程序(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__中查看它的用法