Tkinter: Any way to flush events without blocking?

N

Noah

I have a long running application with a Tkinter GUI.
Is there a way to see how many events are pending in the queue?
I want my application to occasionally process events (so that the
output window will update; the root window will refresh if
the user moves it; etc.).

I tried using Tk.tk.dooneevent(), but it blocks if no events are
available. What I thought of doing is calling a method that
does something like this:
# event_queue_empty() does not exist
while not root.tk.event_queue_empty():
root.tk.dooneevent(0)

The problem is that I'm calling an imported Python method
that runs for a long time. I can't easily retrofit it into an
event-oriented application. What I would like to do is at least
ensure that the root window is up to date before I start the process.
What happens now is that I update the GUI then start the process, but
the root window does not get painted before it freezes while
the imported process runs (about 20 seconds -- a long time for a
GUI to be frozen).

def StartButton (self):
self.label1_text.set ("Processing document")
self.label2_text.set ("Estimated time to complete is
%d seconds." % self.time_estimate)
doc_generator.process (self.document) # do the long
process()

I suppose that my other option is to use a thread, but that
seems overkill when all I want is a updated window.

At this point I suspect that I'm thinking about the problem wrong.

Is there a good source for documentation of the hidden stuff in
Tkinter?
The dooneevent() method seems to be poorly documented. Most docs don't
event mention it (or the tk attribute of a Tk instance). I had to look
up TCL docs to find that dooneevent() is a blocking call.

Yours,
Noah
 
R

Russell E. Owen

I have a long running application with a Tkinter GUI.
Is there a way to see how many events are pending in the queue?
I want my application to occasionally process events (so that the
output window will update; the root window will refresh if
the user moves it; etc.).

I tried using Tk.tk.dooneevent(), but it blocks if no events are
available. What I thought of doing is calling a method that
does something like this:
# event_queue_empty() does not exist
while not root.tk.event_queue_empty():
root.tk.dooneevent(0)

I think this is what you want:
tk_object.update_idletasks()
The problem is that I'm calling an imported Python method
that runs for a long time. I can't easily retrofit it into an
event-oriented application. ....
I suppose that my other option is to use a thread, but that
seems overkill when all I want is a updated window.

update_idletasks() will do what you want.

But you might want to consider a thread anyway. This would be especially
nice if there is any way to add code to the long-running task that would
check to see if the user had aborted. In that case having a thread means
you could implement a responsive "Cancel" button. As far as
communicating from the thread to the main task, there are several
options, including:

- Have the background thread write its output to a Queue and poll the
Queue with an after() loop. This is dirt simple, though a bit
inefficient.
- Have the background thread create an event. Bind a callback to that
event. The callback will run in the main loop, so is safe for writing to
Tk widgets. I read about this neat trick recently on this news group.

(Whatever you do, don't have the background thread try to write to Tk
widgets or set Tk variables. But I assume you know that.)

-- Russell
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,517
Latest member
Andres38A1

Latest Threads

Top