Tkinter: как использовать после метода

Привет, я новичок в python и использую tkinter для своего gui. У меня возникли проблемы с использованием метода "после". Цель состоит в том, чтобы создать случайную букву каждые 5 секунд.

Вот мой код:

import random
import time
from tkinter import *


root = Tk()

w = Label(root, text="GAME")
w.pack()

frame = Frame(root, width=300, height=300)
frame.pack()

L1 = Label(root, text="User Name")
L1.pack(side=LEFT)
E1 = Entry(root, bd =5)
E1.pack(side=LEFT)


tiles_letter = ['a', 'b', 'c', 'd', 'e']


while len(tiles_letter) > 0:
    rand = random.choice(tiles_letter)
    tile_frame = Label(frame, text=rand)
    tile_frame.pack()
    frame.after(500)
    tiles_letter.remove(rand)  # remove that tile from list of tiles

root.mainloop()

Может кто-то, пожалуйста, помогите мне --- проблема, безусловно, frame.after(500): Я не уверен, правильно ли использовать "фрейм", и я не знаю, какой аргумент следует за 500.

Спасибо

Ответы

Ответ 1

Вам нужно дать функцию, которая будет вызываться после временной задержки в качестве второго аргумента after:

после (delay_ms, callback = None, * args)

Регистрирует обратный вызов тревоги, вызываемый по истечении заданного времени.

Итак, что вы действительно хотите сделать, это:

tiles_letter = ['a', 'b', 'c', 'd', 'e']

def add_letter():
    rand = random.choice(tiles_letter)
    tile_frame = Label(frame, text=rand)
    tile_frame.pack()
    root.after(500, add_letter)
    tiles_letter.remove(rand)  # remove that tile from list of tiles


root.after(0, add_letter)  # add_letter will run as soon as the mainloop starts.
root.mainloop()

Вам также нужно запланировать повторную функцию, повторив вызов after внутри функции обратного вызова, так как after выполняет только одну функцию. Это также отмечается в документации:

Обратный вызов вызывается только один раз для каждого вызова этого метода. Хранить вызывая обратный вызов, вам необходимо перерегистрировать обратный вызов внутри Сам

Обратите внимание, что ваш пример генерирует исключение, как только вы исчерпали все записи в tiles_letter, поэтому вам нужно изменить свою логику, чтобы обрабатывать этот случай в зависимости от того, какой вы хотите. Простейшей вещью было бы добавить проверку в начале add_letter, чтобы убедиться, что список не пуст, и просто return, если это:

def add_letter():
    if not tiles_letter:
        return
    rand = random.choice(tiles_letter)
    tile_frame = Label(frame, text=rand)
    tile_frame.pack()
    root.after(500, add_letter)
    tiles_letter.remove(rand)  # remove that tile from list of tiles