Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update Tkinter Label Text before executing some other function?

I am trying to write a small GUI program using Tkinter. What I am trying to do is to create a window with a button and an input, which works just fine. However, I want the button to run some function func which updates the tkinter window and once that is done run whatever comes next:

import tkinter as tk
import time

def func():
    widgets = root.grid_slaves()
    for widget in widgets:
        if int(widget.grid_info()['row']) != 0:
            widget.destroy()
            startPrompt.configure(text="Updated Text")

    startPrompt.update_idletasks()
    # root.update_idletasks()  -- I have tried both and neither work

    # Just an example of something running, to verify that the loop executes 
    # before tkinter window gets updated
    for i in range(10):
        print(i)
        time.sleep(0.5)

font = ("Helvetica", 20)
root = tk.Tk()
startPrompt = tk.Label(root, text="Starting Prompt", font=font)
inputPrompt = tk.Label(root, text="Input Prompt", font=font)
root.textEntry = tk.Entry(root, width=50)
submitButton = tk.Button(root, text="Enter", command=func, width=20, pady=10, font=font)

startPrompt.grid(row=0, columnspan=2, padx=10, pady=10)
inputPrompt.grid(row=1, padx=10, pady=10)
root.textEntry.grid(row=1, column=1, padx=10)
submitButton.grid(row=2, columnspan=2)

root.mainloop()

The problem that I have is that no matter what I try it doesn't work. I've tried using after() but the way my program is written makes it very difficult to rewrite everything such that that would work properly. I have tried using update_idletasks() but that doesn't seem to work either.

Does anyone know why update_idletasks() isn't working or am I using it wrong and is there any way I can solve my issue?

like image 324
djvaroli Avatar asked Aug 27 '26 05:08

djvaroli


1 Answers

Seems to work for me after changing a couple of things (others were mostly just little optimizations).

  1. Changed func() to not use time.sleep() as shown below—the after() universal widget method can (also) be used to do this and using it doesn't interfere with the mainloop() running the way calling sleep() would.
  2. Called the universal widget method update() instead of update_idletasks() after destruction of the widgets—but still before the counting loop runs.

Here's some documentation describing how to use the universal widget method after() this way (as well as what the update() method does).

FWIW: You'll be able see what's happening better if you add something like a root.geometry('600x400') line following the root = tk.Tk() statement in the initialization section of the example code in your question (not shown here) which will prevent the window from resizing after the widgets are destroyed and the display is updated.

def func():
    widgets = root.grid_slaves()
    for widget in widgets:
        if widget.grid_info()['row']:  # Don't need all that int() != 0 stuff.
            widget.destroy()

    startPrompt.configure(text="Updated Text")  # Only need to call once.
    root.update()  # Update display (startPrompt.update() also works here)

    # Just an example of something running, to verify that the loop executes
    # AFTER the tkinter window has been updated.
    for i in range(10):
        print(i)
#        time.sleep(0.5)  # Don't use sleep in tkiner programs.
        root.after(500)  # Pause 500 millisecs.
like image 72
martineau Avatar answered Aug 29 '26 20:08

martineau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!