+-
python-代替tkinter.dooneevent
我正在将程序(VMD,Visual Molecular Dynamics)以C语言编写,并同时嵌入了 Python和TCL解释器,并将其移植到Python3.x.它的大多数UI使用TCL / TK框架和OpenGl进行硬编码,因此UI刷新是手动完成的.当Python解释器运行时,可以动态创建新窗口,甚至可以使用Tkinter向主UI添加新菜单.在这种情况下,通过在Python端定期调用一些代码来刷新所有TK事件(请参见下文).这样可以确保所有更新都是线程安全的,并且不会破坏解释器.

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;
}

但是功能tkinter.dooneevent从Python 3中删除了,我找不到它的替代品.我尝试调用低级的Tcl_DoOneEvent(TCL_DONT_WAIT),但是当我动态创建一个新窗口时,最终导致Python解释器崩溃,并显示致命致命错误:PyEval_RestoreThread:NULL tstate.

tkinter woes when porting 2.x code to 3.x, ‘tkinter’ module attribute doesn’t exist中的答案无济于事,因为我没有用户可能创建的所有窗口的列表.

在这种情况下,有人对如何清除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.

现在,我不知道如何准确地将其转换为您的代码-您是否具有可以访问dooneevent的Tk根对象?我对python 2 tkinter一点都不熟悉,所以我不完全知道我的代码如何均匀地映射到您的代码.但是,我在做与您非常相似的事情时发现了这一点-尝试将tkinter事件循环集成到asyncio事件循环中.我能够创建一个协程,该协程在循环中调用此方法,每次产生(偶尔休眠),以便GUI保持响应状态,而不会使用tkinter._tkinter.create()阻止asyncio事件循环.

@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__中查看其用法.

点击查看更多相关文章

转载注明原文:python-代替tkinter.dooneevent - 乐贴网