When do I need to call mainloop in a Tkinter application?

Question:

Every tkinter tutorial I have seen claims that tkinter.mainloop must be called for windows to be drawn and events to be processed, and they always call this function, even in hello world programs. However, when I try these out in the interactive shell, windows are drawn correctly without having to call mainloop. This example of embedding matplotlib graphics in tkinter produces a relatively complex application, with buttons for panning, zooming and resizing a plot within a tkinter window, and again, this all works if you remove the call to mainloop and run the code in the interactive shell. Of course, if I run the script (with mainloop removed) outside the interactive shell, the program ends too quickly to see what happens, but if I add a call to input to hold the program open everything works correctly (I’m running python 3.2.2 on linux).

So what exactly does mainloop do, and when is it necessary to call it?

EDIT:
To clarify, if I open up the GNOME terminal and type

$python3
>>> import tkinter
>>> root = tkinter.Tk()

a window immediately appears without having to call mainloop, and more complex tkinter functionality seems to work as well (for example, adding buttons to the window). In IDLE, a call to mainloop is necessary. It was my understanding that nothing should be drawn, and no events should be processed, until mainloop is called.

Asked By: James

||

Answers:

Compare a program with an interactive GUI to a program that calculates the hundredth Fibonacci number. All the latter program has to go through a series of steps in order, top to bottom. The set of steps and their sequencing can be known in advance, and it’ll remain constant no matter how many times you run the program.

But the GUI program is different: at any given moment, it has to be able to handle all sorts of different kinds of events and interactions. This requirement is often implemented using a programming construct called an event loop. An event loop is the central control structure of a program. It waits for an event to happen, and then dispatches the appropriate handler.

You didn’t mention which interactive shell you’re using, but I’m guessing it’s IDLE. IDLE itself is a Tkinter program, and it already has an event loop going. So possibly the Tkinter code you are typing into the shell is getting bound to IDLE’s event loop.

Answered By: Ori

The answer to your main question is, you must call mainloop once and only once, when you are ready for your application to run.

mainloop is not much more than an infinite loop that looks roughly like this (those aren’t the actual names of the methods, the names merely serve to illustrate the point):

while True:
    event=wait_for_event()
    event.process()
    if main_window_has_been_destroyed(): 
        break

In this context, “event” means both the user interactions (mouse clicks, key presses, etc) and requests from the toolkit or the OS/window manager to draw or redraw a widget. If that loop isn’t running, the events don’t get processed. If the events don’t get processed, nothing will appear on the screen and your program will likely exit unless you have your own infinite loop running.

So, why don’t you need to call this interactively? That’s just a convenience, because otherwise it would be impossible to enter any commands once you call mainloop since mainloop runs until the main window is destroyed.

Answered By: Bryan Oakley

I’ve decided that, instead of sticking a call directly to mainloop anywhere in my script, I’ll just add it as part of atexit – that is, when the Python interpreter decides it’s time to start closing down, it’s going to enter Tk’s mainloop. This then prevents it from finishing the shut down sequence until the user actually tells Tk to quit (IE, with command-Q on a Mac, or by clicking on the red X in Windows.)

from Tkinter import Tk
root = Tk()

import atexit
atexit.register(root.mainloop)

There seems to be no need to call mainloop from a system command line. The Python interpreter will continue running without it, because it’s waiting for further input from you (until you run exit()).

Answered By: ArtOfWarfare

As follows:

from tkinter import *

tk = Tk()
canvas = Canvas(tk, width=500, height=500)
canvas.pack()
canvas.create_line(0, 0, 500, 500)

mainloop()
Answered By: Balázs Ortutay

When you execute your code, the tkinter window will refuse to open without there being a mainloop function.

For example this will not work:

from tkinter import*
root=Tk()

This, however, will work:

from tkinter import*
root=Tk()
root.mainloop()
Answered By: Xx Stef xX
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.