tkinter 不会刷新小部件

tkinter wont refresh widget

我想写一个只有一个按钮的程序,按下那个按钮后,程序会开始制作 3 个标签,然后每 1 秒改变一次每个标签的颜色。

看起来很简单,我写了下面的代码:

import tkinter as tk
from time import sleep


def function():
    mylist=list()
    for i in range(3):
        new_label=tk.Label(window,text='* * *',bg='yellow')
        new_label.pack()
        mylist.append(new_label)
    print('First state finished')
    sleep(1)
    for label in mylist:
        label.config(bg='red')
        print('one label changed')
        sleep(1)
    
window = tk.Tk()
window.geometry('300x300')

btn=tk.Button(window,text='start',command=function)
btn.pack()

tk.mainloop()

首先,应用程序看起来像这样(没问题):

其次它看起来像这样(它不正常,因为它在终端上打印但没有更新标签):

第三个看起来像这样(最后应用程序必须像这样并且没问题):

但我需要立即查看变化并因此使用睡眠。 谢谢大家。

我建议使用 tkinter 的 .after(delay, callback) 方法来设置颜色。

希望这就是你想要的。

import tkinter as tk


def start():
    global mylist
    mylist = list()
    for i in range(3):
        new_label = tk.Label(window, text='* * *', bg='yellow')
        new_label.pack()
        mylist.append(new_label)

    delay = 1000 # delay in seconds
    for label in mylist:
        # Additional delay so that next color change 
        # is scheduled after previous label color change
        delay += 1000 
        schedule_color_change(delay, label)


def schedule_color_change(delay, label):
    print("schedule color change for:", label)
    label.after(delay, set_color, label)



def set_color(label):
    print("setting color of:", label)
    label.config(bg="red")


window = tk.Tk()
window.geometry('300x300')
btn = tk.Button(window, text='start', command=start)
btn.pack()

tk.mainloop()

问题

问题出在你的sleep(1),因为它是一个暂停当前线程执行一定秒数的函数,所以就像整个脚本都停止了

解决方案

解决方法是用一个目标函数实例化Thread,调用start(),让它开始工作。所以你必须使用包含在线程中的 timer,然后是线程模块中的计时器 (import threading)

在第一个“for”循环中,删除你的 sleep(1) 并写入例如 Time_Start_Here = threading.Timer (2, function_2) 然后当然是 Time_Start_Here.start() 开始。

start_time=threading.Timer(1,function_2)
start_time.start()

相反,您必须删除第二个“for”循环并将其中的内容写入……在将被调用的新函数中。接下来你需要创建函数

def function_2():
    for label in mylist:
        label.config(bg='red')
        label.pack()
        print('one label changed')

Meritor的指导下,我按照after的方法,不眠不休的写了下面的递归代码:

import tkinter as tk


def recursive(i, listt):
    lbl = listt[i]
    if i >= 0:
        lbl.config(bg='orange')
        i -= 1
        lbl.after(500, recursive, i, listt)


def function():
    mylist = list()
    for i in range(3):
        new_label = tk.Label(window, text='* * *', bg='yellow')
        new_label.pack()
        mylist.append(new_label)
    print('all label created')
    # 2 is length of list minus 1
    recursive(2, mylist)


window = tk.Tk()
window.geometry('300x300')

tk.Button(window, text='start', command=function).pack()

tk.mainloop()

很可能我的代码没有优化,因为它使用递归,如果你知道更好的,请告诉我