Python 在tkinter中使用.config

Python 在tkinter中使用.config,python,user-interface,tkinter,Python,User Interface,Tkinter,这里是初学者 在一个简单的倒计时应用程序上更新标签时遇到困难, 有人能解释为什么标签在循环中不更新吗 import time import tkinter as tk root = tk.Tk() root.geometry('150x100') seconds_inp = tk.Entry(root) global time_label time_label = tk.Label(root, text = '00', font = 20) start_button = tk.Button(

这里是初学者 在一个简单的倒计时应用程序上更新标签时遇到困难, 有人能解释为什么标签在循环中不更新吗

import time
import tkinter as tk

root = tk.Tk()
root.geometry('150x100')

seconds_inp = tk.Entry(root)
global time_label
time_label = tk.Label(root, text = '00', font = 20)
start_button = tk.Button(root, text = 'start', command = lambda: countdown_clock(int(seconds_inp.get())))
def countdown_clock(seconds):
    while True:
        seconds = seconds - 1
        time.sleep(1)
        time_label.config(text = seconds)


        print(seconds)
        if seconds == 0:
            time_label.config(text = 'time!')
            break



time_label.grid(row = 1, column = 0)
start_button.grid(row = 2, column = 0)
seconds_inp.grid(row = 3, column = 0)
root.mainloop()

在之后使用
,而不是在
和等待时使用
。而且,你的时钟一开始就减去一秒钟。将减去的值发送到下一个调用。如果您要做的就是将每个小部件粘贴到下一个
中的一个
中,那么您不必在
网格()
中指定,您只需确保以正确的顺序调用小部件上的
网格。如果添加更多列,则规则将更改回您的操作方式

import time
import tkinter as tk

root = tk.Tk()
root.geometry('150x100')

def countdown_clock(s, t):
    if not s:
        t.configure(text='time!')
        return
    
    t.configure(text=s)
    root.after(1000, lambda: countdown_clock(s-1, t))
    


time_lbl     = tk.Label(root, text='00', font=20)
time_lbl.grid()

start_btn    = tk.Button(root, text='start', command=lambda: countdown_clock(int(seconds_ent.get()), time_lbl))
start_btn.grid()

seconds_ent  = tk.Entry(root)
seconds_ent.grid()

root.mainloop()

之后使用
,而不是在
等待时使用
。而且,你的时钟一开始就减去一秒钟。将减去的值发送到下一个调用。如果您要做的就是将每个小部件粘贴到下一个
中的一个
中,那么您不必在
网格()
中指定,您只需确保以正确的顺序调用小部件上的
网格。如果添加更多列,则规则将更改回您的操作方式

import time
import tkinter as tk

root = tk.Tk()
root.geometry('150x100')

def countdown_clock(s, t):
    if not s:
        t.configure(text='time!')
        return
    
    t.configure(text=s)
    root.after(1000, lambda: countdown_clock(s-1, t))
    


time_lbl     = tk.Label(root, text='00', font=20)
time_lbl.grid()

start_btn    = tk.Button(root, text='start', command=lambda: countdown_clock(int(seconds_ent.get()), time_lbl))
start_btn.grid()

seconds_ent  = tk.Entry(root)
seconds_ent.grid()

root.mainloop()

while
循环会导致windows在一段时间后没有响应,因此最好的方法是消除这种情况,并使用内置的
after()
方法

以下是一个工作示例:

import time
import tkinter as tk

root = tk.Tk()
root.geometry('150x100')

seconds_inp = tk.Entry(root)

time_label = tk.Label(root, text='00', font=20)
start_button = tk.Button(
    root, text='start', command=lambda: countdown_clock(int(seconds_inp.get())))


def countdown_clock(seconds):
    seconds = seconds - 1
    time_label.config(text=seconds)
    call = root.after(1000, lambda: countdown_clock(seconds))
    if seconds == 0:
        root.after_cancel(call)
        time_label.config(text='Time up!!')
    print(seconds)


time_label.grid(row=1, column=0)
start_button.grid(row=2, column=0)
seconds_inp.grid(row=3, column=0)
root.mainloop()
我所做的只是,我删除了
while
,因为它会中断
mainloop()
方法,所以我使用
after()
方法连续调用函数,直到
second
达到0,然后取消
after()
并最终更新标签。我删除了函数外部的
global
,因为在函数外部调用这些函数是毫无意义的

希望这消除了你的疑虑


欢呼声

,而
循环会导致windows在一段时间后没有响应,因此最好的方法是消除这种情况,并使用内置的
after()
方法

以下是一个工作示例:

import time
import tkinter as tk

root = tk.Tk()
root.geometry('150x100')

seconds_inp = tk.Entry(root)

time_label = tk.Label(root, text='00', font=20)
start_button = tk.Button(
    root, text='start', command=lambda: countdown_clock(int(seconds_inp.get())))


def countdown_clock(seconds):
    seconds = seconds - 1
    time_label.config(text=seconds)
    call = root.after(1000, lambda: countdown_clock(seconds))
    if seconds == 0:
        root.after_cancel(call)
        time_label.config(text='Time up!!')
    print(seconds)


time_label.grid(row=1, column=0)
start_button.grid(row=2, column=0)
seconds_inp.grid(row=3, column=0)
root.mainloop()
我所做的只是,我删除了
while
,因为它会中断
mainloop()
方法,所以我使用
after()
方法连续调用函数,直到
second
达到0,然后取消
after()
并最终更新标签。我删除了函数外部的
global
,因为在函数外部调用这些函数是毫无意义的

希望这消除了你的疑虑


干杯

用户界面无法更新,因为您被困在使用
时间的循环中。睡眠
。看看
。(…)
之后的
时间。sleep()
正在干扰tkinter的
mainloop()
。您应该能够通过使用通用小部件方法(在调用
config()
之后)来更新
标签。另一种选择是使用universal
after()
widget方法代替
time.sleep()
,因为它不会产生干扰。现在,当Michael给出了下面的有效答案时,正如另一个答案一样,不建议在GUI中使用while循环(特别是在您刚开始时),'因为它经常阻止GUI更新,因为它没有到达
mainloop
。在这些情况下,使用@martineau建议的
update_idletasks()
。即使在您自己的代码中,只要在
time\u label.config(text=seconds)
行之后添加
time\u label.update\u idletasks()
,就可以解决GUI更新中的问题。但是,正如michael所说,要小心一些事情,比如在计时器启动之前减去一秒钟,以及网格安排。@PSSolanki然而,使用
update\u idletaks()
最终会导致窗口没有响应,即使时间过了,GUI也跟不上进度,而且我注意到,这也会导致标签写得太多(虽然我不知道为什么)@PSSolanki-hmmmm,我注意到
update()
update\u idletasks()
对我来说效果更好,如果OP能标记一个答案,关闭QT,用户界面无法更新,因为你使用
time.sleep
卡在循环中。看看
。(…)
之后的
时间。sleep()
正在干扰tkinter的
mainloop()
。您应该能够通过使用通用小部件方法(在调用
config()
之后)来更新
标签。另一种选择是使用universal
after()
widget方法代替
time.sleep()
,因为它不会产生干扰。现在,当Michael给出了下面的有效答案时,正如另一个答案一样,不建议在GUI中使用while循环(特别是在您刚开始时),'因为它经常阻止GUI更新,因为它没有到达
mainloop
。在这些情况下,使用@martineau建议的
update_idletasks()
。即使在您自己的代码中,只要在
time\u label.config(text=seconds)
行之后添加
time\u label.update\u idletasks()
,就可以解决GUI更新中的问题。但是,正如michael所说,要小心一些事情,比如在计时器启动之前减去一秒钟,以及网格安排。@PSSolanki然而,使用
update\u idletaks()
最终会导致窗口没有响应,即使时间过了,GUI也跟不上进度,而且我注意到,这也会导致标签写得太多(虽然我不知道为什么)@PSSolanki-hmmmm,我注意到
update()
update\u idletasks()
对我来说效果更好,如果OP能给出答案,请关闭Q