I have seen the after_idle() function in the last days when doing my
own search for a solution.
I read about it and came to the conclusion that it would not do what I want.
But the description mentioned above seems to change my mind.
Could you explain why you thought that? It is aimed at doing things
after stuff like widget layout has settled, but it’s also a mechanism
for getting a callback inserted into the mainloop, to run once.
I guess it could do the right thing, but I have to do it all the other
way round so that my background thread populates a list of available
image objects, that have been updated and the function which will be
called by mainloop’s after_idle() function will read that list and
update the corresponding widgets.
Yes. To avoid contention I’d have a small object to contain the list,
with a lock. The worker makes an image object, takes the lock and
appends it to the list. The after_idle
callback takes the lock,
switches out the list for an empty one, releases the lock, and processes
the list it collected.
I guess that list should perhaps be a queue as it is suggested as thread safe “communication” channel in tkinter multithread programs.
That can work. The worker would put image objects onto the queue and the
after_idle
callback function would run a quick loop while not q.empty()
to collect images. Not overt locks required because the queue contains
them.
One question concerning the after_idle() methid still remains: It has
to be used on a tkinter widget object as I understand. But it seems, it
does not really matter which one? So I could just use it on the main
window widget and it will do the job?
Yes, or whatever widget is to hand when you’re doing things. The widget
is just the gateway into the tkinter system to call after_idle()
.
Or is the “idle state” only checked for widgets below or even above in hierarchy of widgets in some way? But in my opinion it is all one mainloop and so it should not make a difference…
It doesn’t. The mainloop processes events and updates the GUI. At the
end of each batch of updates it will also run the after_dile
callbacks. Once - it will need resubmitting. Which the callback can do
itself.
It does occur to me that if the GUI’s idle the callback won’t run until
something happens.
Hmm. You could avoid the queue and the alternative pick-up-the-list
approaches entirely. Have the worker submit a callback to process a new
image object for every image. The callbacks submitted with
after_idle()
are effectively a queue, and I would expect them to wake
up the mainloop if it were already idle. This would need to be tested.
But with this approach the worker could go:
... up the top with the imports ...
from functools import partial
... in the worker ...
... prepare a new image object ...
main_widget.after_idle(partial(process_new_image, new_image_object))