tkinter redraw rates
Christian Gollwitzer
auriocus at gmx.de
Thu Jul 18 03:20:28 EDT 2013
Am 18.07.13 06:38, schrieb fronagzen at gmail.com:
> On Thursday, July 18, 2013 9:07:24 AM UTC+8, Dave Angel wrote:
>> Nope - don't use that. Instead, post an event on the queue, and return
>> to the mainloop() from whence we came.
>> def test_thread(self):
>> if self.loader_thread.isAlive():
>> self.root_window.after(100, self.test_thread)
>> return
>
> I see, though it should be noted that your method doesn't actually
> block the rest of the even handler code from running, had to fiddle
> with it a bit to get that to work. May I ask what exactly is the
> rationale behind implementing it like this, though?
>
Exactly this is the goal of it. Event handlers are supposed to run in as
short time as possible, and should never block. The reason is that you
want the events to be processed in the order they come in, such that he
user can still move the window, resize it, iconify/maximize etc.
That said, the code still looks odd to me. I have used the Tk with
multithreading in the past, but directly from Tcl, and not from Python.
The basic idea is to have the background thread (which does the work)
signal the main thread about its status, i.e. in the worker thread:
for i in range(50):
some_odd_computation()
signal('progress', i)
signal('finished')
and in the main thread you bind() to the events fired from the worker
thread. That way you don't run any periodic polling.
I fear that Tkinter has a shortcoming which does not allow this pattern
to be implemented. The tricky thing is to implement this signal()
function, which must post an event to another thread. From the C level,
there is Tcl_ThreadQueueEvent() which does this. It arranges for a C
function to be run from the event loop of another thread. From Tcl,
thread::send does this. To use it from Tkinter, it would be necessary to
create a Tcl interpreter in the worker thread *without* loading Tk.
Some day I should dive into the innards of Tkinter to see if this is
possible. Then you could implement signal() simply by
def signal(sig, data=''):
tclinterp.eval('thread::send -async $mainthread {event generate .
<<%s>> -data {%s}'%sig%data)
and in the main thread bind() to the virtual events.
Christian
More information about the Python-list
mailing list