I am porting a program (VMD, Visual Molecular Dynamics), which is written in C++ and has both Python and TCL interpreters embedded, to Python 3.x. Most of its UI is hard coded using the TCL/TK framework and OpenGl, so UI refreshs are done manually. When the Python interpreter is running it is possible to dynamically create new windows and even add new menus to the main UI using Tkinter. In this case all TK events are flushed by periodically calling some code in the Python side (see below). This ensures that all updates are thread-safe and don't break the interpreter.
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;
}
However the function tkinter.dooneevent
was removed from Python 3 and I can not find a substitute for it. I tried calling the low-level Tcl_DoOneEvent(TCL_DONT_WAIT)
but when I dynamically created a new window I ended up crashing the Python interpreter with the error Fatal Python error: PyEval_RestoreThread: NULL tstate
.
The answers in tkinter woes when porting 2.x code to 3.x, 'tkinter' module attribute doesn't exist doesn't help since I don't have a list of all windows that may created by the user.
Does anyone have any suggestion on how to flush the TK events in this case? It could be either on the Python side or in C++.
Thanks in advance