binding Label in tkinter while function runs

Question:

I have a code where by clicking button, function runs. But inside function there are two labels that I want them to appear with text inside labels while python runs from top to bottom inside function. As it displays in cmd if they were print() statements, whenever cursor reads, and display the message.
But in tkinter it displays after function has been read entirely. How can I manage it?

code is below;

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title("Your App crawler")

mainframe = ttk.Frame(root)

mainframe.grid(column=0, row=0, sticky=('N'))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

feet = tk.StringVar()
feet_entry = ttk.Entry(mainframe, width=21, textvariable=feet)
feet_entry.grid(column=0, row=1, sticky=(tk.N),ipadx=100)
feet_entry.focus()

ttk.Label(mainframe, text="enter  url ").grid(column=3, row=1, sticky=('N'))

def crawler():
    varUrl = feet_entry.get()#input("url (enter) :")


    lblGS = ttk.Label(mainframe).grid(column=1, row=2, sticky=('N'))
    ttk.Label(mainframe, text="...gathered data from SoundCloud " + varStrTitle + " ...").grid(column=0, row=3, sticky='W')
    print('...gathered data from web' + varStrTitle + ' ...')



    lblES = ttk.Label(mainframe).grid(column=1, row=4, sticky=('N'))
    ttk.Label(mainframe, text="...pulled out data also from googlesheets ...").grid(column=0, row=5, sticky='W')
    print('...pulled out data also from googlesheets ...')


button = ttk.Button(mainframe, text="scrape", command=crawler)
button.grid(column=3, row=7, sticky=tk.S)
root.bind("<Return>", crawler)

for child in mainframe.winfo_children():
    child.grid_configure(padx=5, pady=5)
root.mainloop()
Asked By: xlmaster

||

Answers:

Normally every GUI updates window after running user’s function – to make less redrawings and not "blink" on every redraw.

If you have long-running code then you may need to use root.update() after every widget to force tkinter to redraw it at once (before end of function.)


Minimal working code.

I uses time to simulate long-running code.

import tkinter as tk
from tkinter import ttk
import time

# --- functions ---

def crawler():

    ttk.Label(root, text="1").grid(column=0, row=0)
    root.update()

    time.sleep(2)
    
    ttk.Label(root, text="2").grid(column=0, row=1)
    root.update()

    time.sleep(2)

    ttk.Label(root, text="3").grid(column=0, row=2)
    root.update()

    time.sleep(2)

    ttk.Label(root, text="END").grid(column=0, row=3)
    #root.update()

# --- main ---    
    
root = tk.Tk()

button = ttk.Button(root, text="scrape", command=crawler)
button.grid(column=0, row=7)

root.bind("<Return>", crawler)

root.mainloop()

EDIT:

root.update() checks also other elwments – ie. if user clicked button to run other code (ie. to stop function) so it may need more root.update() in function to check it more often.

But for more complex code it may need to run function in separated thread and use queue to send information to main thread, and main thread may need root.after(milliseconds, function) to run function which checks new data in queue and displays it in window.

Answered By: furas