Привет, я новичок в python и использую tkinter для своего графического интерфейса. У меня возникли проблемы с использованием frame.after метода. Цель состоит в том, чтобы заставить случайную букву появляться каждые 5 секунд.
whilelen(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), Я не уверен, правильно ли его использовать frame и я не знаю, какой аргумент следует за 500 параметром.
Спасибо
Переведено автоматически
Ответ 1
Вам нужно указать функцию, которая будет вызываться после временной задержки, в качестве второго аргумента для after:
after(delay_ms, callback=None, *args)
Регистрирует аварийный обратный вызов, который вызывается по истечении заданного времени.
Итак, что вы действительно хотите сделать, так это:
tiles_letter = ['a', 'b', 'c', 'd', 'e']
defadd_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 если это так:
defadd_letter(): ifnot 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
Я полагаю, 500 мс выполняются в фоновом режиме, в то время как остальная часть кода продолжает выполняться и очищает список.
Затем через 500 мс ничего не происходит, поскольку в after-callup не реализован вызов функции (такой же, как frame.after(500, function=None))
Ответ 3
after используется для задержки выполнения программы или для выполнения команды в фоновом режиме когда-нибудь в будущем. Но вы можете создать цикл внутри mainloop, вызвав сам цикл.
import tkinter as tk #import tkinter import datetime #import datetime for our clock
deftick(): #function to update the clock showed_time = clock['text'] #current showed time current_time = datetime.datetime.now().strftime("%H:%M:%S") #real time if showed_time != current_time: #if the showed time is not the real time clock.configure(text=current_time) #update the label with the current time clock.after(1000, tick) #call yourself in 1000ms (1sec.) again to update the clock returnNone
root=tk.Tk()
clock = tk.Label(root) clock.pack() tick()
root.mainloop()
В приведенном выше скрипте мы создали цифровые часы и связались с методом after. Метод after - это не что иное, как интервал, и в конце этого интервала мы хотим, чтобы что-то произошло.
Чтобы узнать больше об этом базовом методе виджета [нажмите]
after(delay_ms, обратный вызов = Нет, аргументы)
Этот метод регистрирует функцию обратного вызова, которая будет вызвана через заданное количество миллисекунд. Tkinter только гарантирует, что обратный вызов не будет вызван раньше этого времени; если система занята, фактическая задержка может быть намного больше.
import tkinter as tk import datetime
deftick(): showed_time = clock['text'] current_time = datetime.datetime.now().strftime("%H:%M:%S") if showed_time != current_time: clock.configure(text=current_time) global alarm #make sure the alarm is reachable alarm = clock.after(1000, tick)#assign the alarm to a variable returnNone defstop(): stop.after_cancel(alarm) #cancel alarm
Здесь у нас есть тот же код, но с возможностью отменить наш цикл с помощью after_cancel метода tkinter. Вам не нужно глобализировать сигнал тревоги внутри класса. self.alarm = self.clock.after(...) работает нормально.