Что такое mainloop в python
Перейти к содержимому

Что такое mainloop в python

  • автор:

mainloop() function in python

I want label to be packed when the user inputs a and when the user inputs b i want label2 to be packed. I am not sure when and why to use mainloop. Right now when I run the program, the GUi only pops up after I have inputted something and then I can’t even input anything else and I think it has some thing to do with the window.mainloop() function because it just loops over and over again instead of running the while True loop again.

asked Jun 13, 2015 at 23:39
1,097 4 4 gold badges 16 16 silver badges 23 23 bronze badges

1 Answer 1

I was able to understand your question better based off of the comment. Let me know if this is what you’re looking for:

import tkinter as tk class HelloWorld(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.entry = tk.Entry(self) self.button = tk.Button(self, text="What's your input?", command=self.on_button) self.button.pack() self.entry.pack() def on_button(self): answer = self.entry.get() if answer == "a": print("Hello World") elif answer == "b": print("Hello World 2") elif answer == "c": root.destroy() root = HelloWorld() root.mainloop() 

So when dealing with the input of a user it’s better to create a class and from that obtain/compare the information.

Now if the answer is anything other than a , b , or c there will be no response from the program, so adjust accordingly.

Tkinter understanding mainloop

Till now, I used to end my Tkinter programs with: tk.mainloop() , or nothing would show up! See example:

from Tkinter import * import random import time tk = Tk() tk.title = "Game" tk.resizable(0,0) tk.wm_attributes("-topmost", 1) canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0) canvas.pack() class Ball: def __init__(self, canvas, color): self.canvas = canvas self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) def draw(self): pass ball = Ball(canvas, "red") tk.mainloop() 

However, when tried the next step in this program (making the ball move by time), the book am reading from, says to do the following. So I changed the draw function to:

def draw(self): self.canvas.move(self.id, 0, -1) 

and add the following code to my program:

while 1: ball.draw() tk.update_idletasks() tk.update() time.sleep(0.01) 

But I noticed that adding this block of code, made the use of tk.mainloop() useless, since everything would show up even without it. At this moment I should mention that my book never talks about tk.mainloop() (maybe because it uses Python 3) but I learned about it searching the web since my programs didn’t work by copying book’s code! So I tried doing the following that would not work.

while 1: ball.draw() tk.mainloop() time.sleep(0.01) 

What’s going on? What does tk.mainloop() ? What does tk.update_idletasks() and tk.update() do and how that differs from tk.mainloop() ? Should I use the above loop? tk.mainloop() ? or both in my programs?

1 1 1 silver badge
asked Mar 20, 2015 at 2:09
1,523 3 3 gold badges 18 18 silver badges 23 23 bronze badges
About mainloop: stackoverflow.com/questions/8683217/…
Mar 20, 2015 at 2:34

these question are connected somehow. i don’t think it would be nice making 3 questions in 3 topics that talk almost about the same thing. 😐

Mar 20, 2015 at 2:34
I suggest getting a different book.
Aug 2, 2022 at 17:29
Working links: Here you have something about the update function. Here about update_idletasks ..
Aug 2, 2022 at 17:41

3 Answers 3

tk.mainloop() blocks. It means that execution of your Python commands halts there. You can see that by writing:

while 1: ball.draw() tk.mainloop() print("hello") #NEW CODE time.sleep(0.01) 

You will never see the output from the print statement. Because there is no loop, the ball doesn’t move.

On the other hand, the methods update_idletasks() and update() here:

while True: ball.draw() tk.update_idletasks() tk.update() 

. do not block; after those methods finish, execution will continue, so the while loop will execute over and over, which makes the ball move.

An infinite loop containing the method calls update_idletasks() and update() can act as a substitute for calling tk.mainloop() . Note that the whole while loop can be said to block just like tk.mainloop() because nothing after the while loop will execute.

However, tk.mainloop() is not a substitute for just the lines:

tk.update_idletasks() tk.update() 

Rather, tk.mainloop() is a substitute for the whole while loop:

while True: tk.update_idletasks() tk.update() 

Response to comment:

Here is what the tcl docs say:

Update idletasks

This subcommand of update flushes all currently-scheduled idle events from Tcl’s event queue. Idle events are used to postpone processing until “there is nothing else to do”, with the typical use case for them being Tk’s redrawing and geometry recalculations. By postponing these until Tk is idle, expensive redraw operations are not done until everything from a cluster of events (e.g., button release, change of current window, etc.) are processed at the script level. This makes Tk seem much faster, but if you’re in the middle of doing some long running processing, it can also mean that no idle events are processed for a long time. By calling update idletasks, redraws due to internal changes of state are processed immediately. (Redraws due to system events, e.g., being deiconified by the user, need a full update to be processed.)

APN As described in Update considered harmful, use of update to handle redraws not handled by update idletasks has many issues. Joe English in a comp.lang.tcl posting describes an alternative:

So update_idletasks() causes some subset of events to be processed that update() causes to be processed.

  1. Keeping the GUI alive while some long-running calculation is executing. See Countdown program for an alternative. 2) Waiting for a window to be configured before doing things like geometry management on it. The alternative is to bind on events such as that notify the process of a window’s geometry. See Centering a window for an alternative.

Is there any chance I can make my program work without the while loop?

Yes, but things get a little tricky. You might think something like the following would work:

class Ball: def __init__(self, canvas, color): self.canvas = canvas self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) def draw(self): while True: self.canvas.move(self.id, 0, -1) ball = Ball(canvas, "red") ball.draw() tk.mainloop() 

The problem is that ball.draw() will cause execution to enter an infinite loop in the draw() method, so tk.mainloop() will never execute, and your widgets will never display. In gui programming, infinite loops have to be avoided at all costs in order to keep the widgets responsive to user input, e.g. mouse clicks.

So, the question is: how do you execute something over and over again without actually creating an infinite loop? Tkinter has an answer for that problem: a widget’s after() method:

from Tkinter import * import random import time tk = Tk() tk.title = "Game" tk.resizable(0,0) tk.wm_attributes("-topmost", 1) canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0) canvas.pack() class Ball: def __init__(self, canvas, color): self.canvas = canvas self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) def draw(self): self.canvas.move(self.id, 0, -1) self.canvas.after(1, self.draw) #(time_delay, method_to_execute) ball = Ball(canvas, "red") ball.draw() #Changed per Bryan Oakley's comment tk.mainloop() 

The after() method doesn’t block (it actually creates another thread of execution), so execution continues on in your python program after after() is called, which means tk.mainloop() executes next, so your widgets get configured and displayed. The after() method also allows your widgets to remain responsive to other user input. Try running the following program, and then click your mouse on different spots on the canvas:

from Tkinter import * import random import time root = Tk() root.title = "Game" root.resizable(0,0) root.wm_attributes("-topmost", 1) canvas = Canvas(root, width=500, height=400, bd=0, highlightthickness=0) canvas.pack() class Ball: def __init__(self, canvas, color): self.canvas = canvas self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) self.canvas.bind("", self.canvas_onclick) self.text_id = self.canvas.create_text(300, 200, anchor='se') self.canvas.itemconfig(self.text_id, text='hello') def canvas_onclick(self, event): self.canvas.itemconfig( self.text_id, text="You clicked at (<>, <>)".format(event.x, event.y) ) def draw(self): self.canvas.move(self.id, 0, -1) self.canvas.after(50, self.draw) ball = Ball(canvas, "red") ball.draw() #Changed per Bryan Oakley's comment. root.mainloop() 

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

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.

15.8k 34 34 gold badges 116 116 silver badges 206 206 bronze badges
asked Dec 30, 2011 at 19:27
3,211 1 1 gold badge 23 23 silver badges 39 39 bronze badges

6 Answers 6

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.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *