Roland's homepage

My random knot in the Web

On the nature of GUI programs

This is based on answers (1, 2) I gave on stackoverflow. That answer is specific to the tkinter toolkit that comes with Python. The principles apply to other GUI toolkits and languages as well but the terminology used (like mainloop and idle task) may be different.

GUI toolkits like tkinter are event-driven. To work properly, the mainloop must continuously be able to process keyboard and mouse events. When it is not processing events, it will start scheduled idle tasks.

So they work quite differently from normal Python scripts that just run from top to bottom.

A tkinter program runs within the “mainloop“. So there are only three things you do before starting the mainloop.

  1. Create a window with some widgets on it.
  2. Create objects (variables) that hold program state.
  3. Define functions that can be run from the mainloop as callbacks or idle tasks.

Usually I tend to wrap the creation of the window and widgets up in a function. This makes the program easier to read. We need to keep references to some of the widgets (e.g. to get the text from an Entry). So those I tend to put in a types.SimpleNamespace that is returned by the function. This makes it easy to access them later.

With regard to (2), I like to wrap those up in a types.SimpleNamespace as well for the same reason.

A callback is called from within the mainloop in response to activating a control (like clicking on a button). An idle task is started by the system after a specified number of milliseconds when the system is not busy processing events. You can schedule idle tasks with the Tk.after() method.

Basically, the callbacks and idle tasks are your program.

It is important to understand that the callbacks and idle tasks both interrupt the mainloop. As long as a callback or idle task is running, the mainloop is not processing events, and your GUI is unresponsive. This means that you cannot have long-running loops in a callback or idle task.

Luckily, in Python 3 tkinter is supposed to be thread-safe provided that the tcl/tk is uses was built with support for threads. That means you can use threads for long-running tasks, and it should be safe to call tkinter functions and methods from such a thread.

For comments, please send me an e-mail.

Related articles

←  Have Python log to syslog Switching to SSH keys for github  →