There is my terrible code and there is a loop, the result of which must be constantly updated in tkinter.Label . Experience in programming is not enough, I can not understand the classes and areas of visibility.

In general, the bottom line is that a label created inside create_widgets() must be updated from the result of a for _ in range(30) loop. Functions inside start_reading() are used only there, so it seemed to me an acceptable idea to put functions inside another function (method?). I found this question , but it did not really help me, unfortunately.

Now I'm specifically confused and ask for help. How to fix the code to fix the problem?

 import tkinter as tk class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) self.create_widgets() def create_widgets(self): ... # Здесь должен быть лейбл def get_resolution(self, handle, client=True): ... def configuration(self): ... def start_reading(self, arg): a = ... b = ... def get_area(self, resolution, area, foo=None): ... spam = get_area(...) eggs = get_area(...) def get_hash(self, img): ... for _ in range(30): # Лейбл должен изменятся каждый раз ... # при изменении result, т.е. 30 раз result = ... del a # После цикла должны быть удалены a и b. del b # Только там не переменные на самом деле, а # .DeleteDC, .ReleaseDC и подобная ересь if __name__ == '__main__': root = tk.Tk() app = Application(master=root) app.configuration() app.mainloop() 
  • I don’t remember exactly, in my opinion, instance_label.configure (text = 'New text') or instance_label.config (text = 'New text') - Xyanight

2 answers 2

The idiomatic way to loop the update of a GUI element is root.after() :

 #!/usr/bin/env python3 import tkinter def loop(n): label['text'] = str(n) root.after(500, loop, n+1) # call loop(n+1) in 0.5 seconds root = tkinter.Tk() label = tkinter.Label(font=(None, 100)) label.pack() root.after_idle(loop, 0) # start loop root.after(5000, root.destroy) # quit in 5 seconds # center window root.eval('tk::PlaceWindow %s center' % root.winfo_pathname(root.winfo_id())) root.mainloop() 

The whole loop in the loop() function. Another example: countdown() function .

Note that you should NOT use an explicit loop with time.sleep() , otherwise the GUI is suspended / frozen:

 #XXX DO NOT DO IT for n in range(10): label['text'] = str(n) time.sleep(0.5) 

Event handlers (such as keystrokes, mouse movement, callback , programmatically scheduled using root.after() ) are executed in one GUI thread, so if the thread is sleeping on the time.sleep() line or is spinning in a long / eternal loop, then no other events are handled — the GUI “hang” effect.

You can try to save this code using label.update() and root.update_idletasks() , but the root.after() version is more flexible and reliable.

Related question: Python multitasking: perform two long functions at the same time, without blocking the GUI .

     import tkinter as tk class Application(tk.Frame): def __init__(self, master=None): super().__init__() self.create_widgets() def create_widgets(self): self.label = tk.Label(text='None') # лейбл self.label.pack() def start_reading(self, arg): if arg: self.label['text'] = arg # Лейбл должен изменятся каждый раз self.label.update() # обновить Лейбл root.after(500, self.start_reading, arg - 1) # repeat the call if __name__ == '__main__': root = tk.Tk() app = Application(master=root) root.after(1000, app.start_reading, 30) # запустить start_reading после 1000ms app.mainloop() 
    • +1 Now you can self.label.update() — it’s enough that root.after() returns control to the event loop. - jfs
    • This question does not apply, but general notes on the code: the master parameter must either be removed, or it must also be explicitly specified in the Frame and the parent Label. It is better not to inherit from Frame at all, and if it is necessary, then delegate the calls. For this example, it would be possible to do without a class at all — the class is needed here so that label and root do not make global or explicitly pass them as parameters to start_reading() - jfs
    • @jfs Thanks for the comments! The construction of the program was based on the code from the documentation: goo.gl/v6QN3P - Trajectory
    • @Trajectory: 1- the code in the documentation uses the master and explicitly transfers the parent. 2- There may be arguments for inheritance from a Tk widget such as Frame, Tk . But composition may be preferable to inheritance (in the 90s and early 200x, the prevailing OOP style abused inheritance, which led to problems). See how OOP in modern languages ​​such as Go is represented. 3- For a specific example of updating the Label in a loop, the focus should be on root.after() (but this is a matter of taste, how to provide an explanation). - jfs