如何使用 "for" 循环和时间延迟替换变量?我正在使用 Python 和 Tkinter

How can I replace a variable using a "for" loop and a time delay? I'm using Python and Tkinter

我想为我的一个应用程序中的功能创建一种“加载”window。我试过进度条,但我想试试这个,看看它如何比较。这个想法是在单击按钮时打开一个新的 window。新的 window 将包含单词“Loading”,然后将包含一个句号“.”。在短时间延迟后附加到它。我已经使用了 time.sleep() 函数,但它的表现并不尽如人意。

我将包含以下代码:

from tkinter import *
from tkinter.ttk import *
from tkinter import Button, Tk, HORIZONTAL
import time

def new_window():
    variable_text = "Loading"
    new_windy = Toplevel(main_window)
    new_windy.title("New_Windy")
    new_windy.geometry("200x200")
    for i in range(10):
        time.sleep(0.3)
        new_windy.update_idletasks()
        variable_text += "."
        label = Label(new_windy, text=variable_text)
        label.pack()

main_window = Tk()
main_window.title("AWESOME_SAUCE")
main_window.geometry('600x600')


button = Button(main_window, text="click_me", command=new_window)
button.pack()

main_window.mainloop()

上面的代码在单击按钮时创建了新的 window,但它并没有用附加的句号“.”替换每次迭代中的“加载”一词,而是创建了 10 个版本的单词“loading”堆叠在自身上,并带有连续的句点数。

使用 label.config() 来编辑已经打包的标签。

from tkinter import *
from tkinter.ttk import *
from tkinter import Button, Tk, HORIZONTAL
import time

def new_window():
    variable_text = "Loading"
    new_windy = Toplevel(main_window)
    new_windy.title("New_Windy")
    new_windy.geometry("200x200")
    label = Label(new_windy, text=variable_text)
    for i in range(10):
        time.sleep(0.3)
        new_windy.update_idletasks()
        variable_text += "."
        label.config(text=variable_text)
        label.pack()

main_window = Tk()
main_window.title("AWESOME_SAUCE")
main_window.geometry('600x600')


button = Button(main_window, text="click_me", command=new_window)
button.pack()

main_window.mainloop()

我有两种方法可以做到这一点。一种是使用单词列表和 after(),另一种是在句子末尾添加点。

方法一: 首先,创建一个包含所有过渡词的列表:

transition = ['Loading','Loading.','Loading..','Loading...','Loading....','Loading.....']

现在您需要索引此列表并调用标签上的每个项目,例如:

count = 0 #a number to index the list
def new_window():
    new_windy = Toplevel(main_window)
    new_windy.title("New_Windy")
    new_windy.geometry("200x200")

    def change():
        global count #globalize it
        rep = main_window.after(1000,change) #repeat the function every 1 second
        try: #to catch the index error
            label.config(text=transition[count]) #change the text with the list index
        except IndexError: #to get past the error showing up
            main_window.after_cancel(rep) #stop the repetition if no more items left to show
        count += 1 #increase the number by 1 over each repetition
        
    label = Label(new_windy, text=transition[count]) #initially set the text to first element
    label.pack()

    change() #call the function for the first time

transition = ['Loading','Loading.','Loading..','Loading...','Loading....','Loading.....']

方法二: 还有另一种方法,就像您使用 += '.' 所做的一样。那就像:

def new_window():
    global text #globalize the main text
    
    new_windy = Toplevel(main_window)
    new_windy.title("New_Windy")
    new_windy.geometry("200x200")

    text = 'Loading' #set the main text 
    def change():
        global text #globalize the new text
        text += '.' #add . over each iteration

        rep = main_window.after(1000,change) #repeat the function every 1 second

        label.config(text=text) #change the text to new text
        if len(text) >= 7+5: #here 7 is the length of word 'Loading' and 5 is the maximum number of dots needed.
            main_window.after_cancel(rep) #stop repeating the function

    label = Label(new_windy, text=text) #set the main text at first
    label.pack()

    change() #call the function initially.

现在进行一些解释:

but it is not quite behaving as it should.

那是因为 time.sleep()mainloop() 混淆导致无响应。因此 GUI 冻结,因此我们必须使用不冻结 GUI 的 after()。不仅 time.sleep()whilefor 循环也会与 mainloop() 混淆,导致 GUI 无响应。

it just creates 10 versions of the word "loading" stacked on itself with successive numbers of full stops.

那是因为每次代码为运行时,都会创建一个带有文本“Loading”的新标签,您要做的是,创建一次文本,然后使用config()稍后更改文本。

事实上,您的导入稍后会给您带来麻烦,您正在使用 ttk 中的小部件编写 tkinter 小部件,因此更改您的导入语句并相应地调整代码,例如:

import tkinter as tk
from tkinter import ttk

现在如果你想要一个 tkinter 小部件使用,tk.Label() 或者如果你想要一个 ttk 小部件,使用 ttk.Label() 等等。

根据您对“正在加载”的要求,当 window 弹出时首先显示,然后在一段时间后显示“。”出现,为此我们可以将其视为两个过程。在第一个中,我们需要打印“Loading”,然后是“.”。为此,我让 for 循环迭代两次,第二次,time.sleep() 用于在“.”之前提供一些时间。出现。

请参考以下修改代码

from tkinter import *
from tkinter.ttk import *
from tkinter import Button, Tk, HORIZONTAL
import time

def new_window():
    variable_text = "Loading"
    new_windy = Toplevel(main_window)
    new_windy.title("New_Windy")
    new_windy.geometry("200x200")
    label = Label(new_windy, text=variable_text)
    for i in range(2):
        new_windy.update_idletasks()
        if i == 1:
            time.sleep(3)
            variable_text += "."
        label.config(text=variable_text)
        label.pack()

main_window = Tk()
main_window.title("AWESOME_SAUCE")
main_window.geometry('600x600')


button = Button(main_window, text="click_me", command=new_window)
button.pack()

main_window.mainloop()