Изменить виджет записи tkinter несколько раз после нажатия кнопки - PullRequest
0 голосов
/ 27 мая 2018

У меня есть виджет tkinter Entry, и когда пользователь нажимает кнопку, содержимое обновляется:

from tkinter import *
window = Tk()

def abcdef(num):
    ent.config(state=NORMAL)
    ent.delete(0, 'end')
    ent.insert(0, num)
    ent.config(state = "readonly")
    print(num) #Just to check the code is being run

def changeEntry():
    for j in range(3):
            ent.after(1000, abcdef(j))



ent = Entry(widow, text="", state = "readonly", readonlybackground="white", font = "20")
ent.grid(row = 0, column = 0, columnspan = 3, sticky = "E")

btn = Button(window, text="Button", command=changeEntry)
btn.grid(row = 1, column = 0, sticky = "NESW", pady = 10, padx = 10)

window.mainloop()

Когда я нажимаю кнопку, окно останавливается на 3 секунды, а затем просто отображает окончательное число.Как сделать так, чтобы, когда пользователь нажимал кнопку, запись менялась каждую секунду, а не просто зависала на 3 секунды, а отображала только окончательную?

Заранее спасибо

1 Ответ

0 голосов
/ 27 мая 2018

У вас две проблемы с этим вызовом .after.Метод .after сообщает Tkinter, чтобы он вызывал функцию, которую вы передаете, по истечении интервала времени.Но вы говорите Tkinter сделать 3 вещи после 1000 миллисекунд, так что все они будут происходить друг на друге.Таким образом, вы должны пошатнуться.

Во-вторых, вам нужно дать .after функцию для вызова, когда пришло время ее вызывать.Но ваш код вызывает функцию и возвращает .after возвращаемое значение вашей функции.Мы можем исправить это, поместив вызов функции в другую функцию.Удобный способ сделать это - использовать lambda, давая lambda аргумент по умолчанию, который он может передать abcdef

import tkinter as tk
window = tk.Tk()

def abcdef(num):
    ent.config(state=tk.NORMAL)
    ent.delete(0, 'end')
    ent.insert(0, num)
    ent.config(state = "readonly")
    print(num) #Just to check the code is being run

def changeEntry():
    for j in range(3):
            ent.after(1000 * j, lambda num=j: abcdef(num))


ent = tk.Entry(window, text="", state = "readonly", readonlybackground="white", font = "20")
ent.grid(row = 0, column = 0, columnspan = 3, sticky = "E")

btn = tk.Button(window, text="Button", command=changeEntry)
btn.grid(row = 1, column = 0, sticky = "NESW", pady = 10, padx = 10)

window.mainloop()

Я также заменил этот "звездный" импорт на более аккуратный import tkinter as tk.Это делает очевидным, какие имена происходят из Tkinter, а какие являются локальными для вашей программы.


Брайан Оукли отмечает, что нам не нужен lambda, мы можем передавать аргументы после функцииназвание.Подробнее см. Основные методы виджетов в документации по Tkinter.Таким образом, мы можем переписать changeEntry так:

def changeEntry():
    for j in range(3):
        ent.after(1000 * j, abcdef, j)

Спасибо, Брайан!

...