Python – How do I update the Tkinter tag text before performing other functions?

How do I update the Tkinter tag text before performing other functions?… here is a solution to the problem.

How do I update the Tkinter tag text before performing other functions?

I’m trying to write a small GUI program using Tkinter. What I want to do is create a window with buttons and input, and it works great. However, I’d like the button to run some function func to update the tkinter window, and run whatever happens next once it’s done :

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 I’m having 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 to make it work. I’ve tried using update_idletasks() but it doesn’t seem to work either.

Does anyone know why update_idletasks() doesn’t work, or am I using it wrong? Is there any way to solve my problem?

Solution

Seems to work for me after changing something (others are mostly just minor optimizations).

  1. Change func() to not use time.sleep() as follows — after() can (also) do this using the generic widget method, and using it doesn’t interfere with mainloop() to call sleep() way to run. <
  2. Call the generic widget method update() instead of update_idletasks() after the widget is destroyed — but still before the count loop runs

Here are some documentation describes how to use the generic widget method in this way after() (And what the update() method does).

FWIW: If you add a line like root.geometry('600x400') after root=, you'll be able to better understand what's going on. Tk() statement in the initialization section of the sample code in your question (not shown here), which will prevent the window from resizing after the widget is destroyed and the display update is displayed.

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.

Related Problems and Solutions