Как динамически заменить метку tkinter (обновленные данные находятся в цикле for)

#python-3.x #tkinter

#python-3.x #tkinter

Вопрос:

У меня есть функция, которая запускается только после нажатия кнопки tkinter. Внутри функции есть цикл for, который выполняет итерацию по набору данных, который я хотел бы динамически отображать через метку tkinter. То есть будет только 1 метка tkinter, и ее значение будет постоянно меняться между итерациями в цикле for .

Самое близкое, что я получил, это то, что на каждой итерации будет создаваться новая метка, и она продолжает расширяться внизу, что не то, что я ищу. Кто-нибудь может посоветовать мне какое-либо возможное направление, которое я могу предпринять?

Ниже приведена структура кодов, которые я пробовал.

 root = tk.Tk()

order_json = tk.StringVar()

def update_label(order):
     order_json.set(order)
     root.update()

def order_func():
     for i in range(len(dataset)):
          data_to_display = dataset[i]

          label = tk.Label(root, textvariable=order_json)
          label.pack()
          update_label(order)

  

таким образом, вместо одной метки, которая постоянно обновляется, каждая итерация создает новую метку под старой, и она просто продолжает расширяться.

введите описание изображения здесь

Я был бы признателен, если кто-нибудь сможет помочь мне. Спасибо.

Ответ №1:

Мы не можем использовать for while циклы or для обновления в реальном времени в графическом интерфейсе tkinter, это потому, что tkinter уже находится в режиме a, из- mainloop за чего использование for цикла or while заставляет графический интерфейс перестать отвечать до окончания цикла, но если for цикл или while цикл невелики и заканчиваются, мы можем использовать их, как если бы мы хотели 10метки во фрейме, которые мы можем просто использовать

 for i in range(10):
   Label(root, text='Label %s' %i).pack()
  

Но если вам нужно время от времени видеть изменения динамически, в вашем случае обновите метку, чтобы увидеть набор данных. Для этих целей мы используем after(ms, callback, args) . Также не используйте sleep вместо этого use after(ms) без какого-либо обратного вызова.

Допустим, я хочу увидеть подсчет. В котором я просто хочу, чтобы метка обновлялась каждые 0,5 секунды, я могу использовать что-то вроде этого.

Пример

 import tkinter as tk

root = tk.Tk()

Label = tk.Label(root, text=1, font=('', 20))
Label.pack()

def update(count=1):
    Label['text'] = count
    # 500ms , calling the same function again and again.
    root.after(500, update, count 1)

update()
root.mainloop()
  

Теперь ответьте на вашу проблему

Поскольку я не знаю, что dataset это такое, я просто беру список от 1 до 50.

Код:

 import tkinter as tk

root = tk.Tk()
root.geometry('200x200')

order_json = tk.StringVar()

dataset = [i for i in range(50)]
label = tk.Label(root, textvariable=order_json, font=('', 20))
label.pack()

count = 1
def order_func():
    global dataset, count
    if count>=len(dataset): return     # This will exit the function when done
    order_json.set(dataset[count])     # This will update the label 
    count  = 1
    root.after(100, order_func)        # This will recall the callback function

tk.Button(root, text='Play', command=order_func).pack()

tk.mainloop()