tkinter: не изменяя значение метки при прохождении цикла for, он удаляет только конечное значение

#python #user-interface #tkinter

#python #пользовательский интерфейс #tkinter

Вопрос:

Я создал пользовательский интерфейс tkinter для некоторого скрипта python для обработки файлов. Когда мы выбираем каталог, он возвращает файлы в каталоге, а затем принимает каждый файл с помощью цикла for и отображает «обработанные файлы» для итерации reach. следовательно, количество обработанных файлов должно быть изменено с 0 на общее количество файлов в каталоге.

 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()
  

Но здесь поле «Обработанные файлы» возвращает номер последнего файла вместо изменения метки с 1-го номера файла на последний в каталоге. Как я могу решить эту проблему?

Ответ №1:

Окно будет обновляться, когда оно простаивает. Здесь он будет помещать в очередь все изменения в GUI, пока не будет выполнена вся обработка, а затем обновит окно после завершения цикла for. Поэтому вы увидите только последнее состояние.

Вы можете заставить root обновляться с root.update() помощью или root.update_idletasks() :

 root.update()           # Update GUI after removing labels amp; 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)
  

Я не уверен, почему root.update_idletasks() это не работает, когда я использую его перед циклом for, но root.update() работает.