I have Created a tkinter UI for some file processing python script. When we choose a directory, then it will return the files in the directory, and then it will takes the each files by using a for loop and it will display 'processed files' for reach iteration. hence the Processed files number have to be change from 0 to the total number of files in the directory.

import os
import time
from tkinter import *
from tkinter import filedialog
import tkinter as tk
root = Tk()
root.title("Demo")
root.geometry('550x300')
root.resizable(width=False, height=False)
def start(userInput,):
    e1.configure(text=userInput.get())
    print(userInput.get())
    ll.destroy()
    e1.destroy()
    browse_btn.destroy()
    st_btn.destroy()
    folder_path = userInput.get()
    path = folder_path
    TEST_IMAGE_PATHS = [f for f in os.listdir(path) if f.endswith('.jpg')]
    # print(TEST_IMAGE_PATHS)
    Total_No_Files = len(TEST_IMAGE_PATHS)
    II_l2_prompt="Total number of files   "
    II_l2 = Label(root, text=II_l2_prompt, width=22, font=("Arial", 11))
    II_l2.place(x=30, y=160, height=25)

    II_l3_prompt = str(Total_No_Files)
    II_l3 = Label(root, text=II_l3_prompt, width=len(II_l3_prompt), font=("Arial", 11))
    II_l3.place(x=240, y=160, height=25)
    II_l4_prompt="Processed files         "
    II_l4 = Label(root, text=II_l4_prompt, width=22, font=("Arial", 11))
    II_l4.place(x=30, y=210, height=25)
    my_string_var = tk.StringVar()
    II_l5_prompt=0
    my_string_var.set(II_l5_prompt)
    II_l5 = Label(root, textvariable=my_string_var, width=len(str(my_string_var)), font=("Arial", 11))
    II_l5.place(x=240, y=210, height=25)

    for e in TEST_IMAGE_PATHS:
        II_l5_prompt += 1
        # time.sleep(2)

        my_string_var.set(II_l5_prompt)

def browse(userInput):

    File_path = filedialog.askdirectory(title='Select Folder')
    if File_path:
        File_name = os.path.basename(File_path)
        # print(File_name)
        e1.delete(0, "end")  # delete all the text in the entry
        e1.insert(0, File_path)
        e1.config(fg='black')

ll = Label(root, text="Path", font=("Arial", 12))
ll.place(x=30, y=110, height=25, width=39)

userInput = StringVar()

e1 = Entry(root,bd=1, textvariable=userInput,width=35, font=("Arial", 12))
e1.insert(0, 'Choose')
e1.config(fg='grey')
e1.bind('<Return>', (lambda event: browse(userInput)))
e1.place(x=80, y=110, height=25)

browse_btn = Button(root, text='Browse',width="10", height=5, bd=0, bg="grey",fg='white',  command=(lambda: browse(userInput)))
browse_btn.place(x=420, y=105, height=35)
st_btn = Button(root, text='Start',width="10", height=5, bd=0,bg="grey",fg='white',  command=(lambda: start(userInput,)))
st_btn.place(x=150, y=200, height=35)
root.mainloop()

But here the 'Processed files' field is returning the last file number instead of changing the label from 1st file number to last in the directory. How can i solve this issue?

1 Answers

0
figbeam On Best Solutions

The window will update when it's idle. Here it will queue all changes to the GUI until all processing is done and then update the window after the for loop exits. Therefore you will only see the last state.

You can force root to update with root.update() or root.update_idletasks():

root.update()           # Update GUI after removing labels & buttons
for e in TEST_IMAGE_PATHS:
    II_l5_prompt += 1
    my_string_var.set(II_l5_prompt)
    root.update_idletasks() # Update GUI after changing II_l5_prompt
    time.sleep(2)

I'm not sure why root.update_idletasks() doesn't work when I use it before the for loop, but root.update() works.