我需要减慢python tkinter应用程序中的循环速度

我需要减慢python tkinter应用程序中的循环速度,python,tkinter,delay,Python,Tkinter,Delay,我有一个相当简单的应用程序的问题。 它运行正常,但我希望它运行得慢一点 其思想是从列表中随机生成一个名称,显示该名称,然后在每次单击按钮时将其从列表中删除 为了让它更有趣一点,我希望程序在开始之前显示几个名称 选择最后一个。为此,我使用了一个简单的for循环。然而,代码执行得如此之快,最后显示的唯一名称是最后一个 使用time.sleep()只会延迟姓氏的显示。没有显示其他名称 这是我的密码: #!/usr/bin/env python3 # -*- coding: utf-8 -*- fro

我有一个相当简单的应用程序的问题。 它运行正常,但我希望它运行得慢一点

其思想是从列表中随机生成一个名称,显示该名称,然后在每次单击按钮时将其从列表中删除

为了让它更有趣一点,我希望程序在开始之前显示几个名称 选择最后一个。为此,我使用了一个简单的for循环。然而,代码执行得如此之快,最后显示的唯一名称是最后一个

使用
time.sleep()
只会延迟姓氏的显示。没有显示其他名称

这是我的密码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from tkinter import *
import random
import time

class Application(Frame):
    def __init__(self, master):
        """ Initialize the frame. """
        super(Application, self).__init__(master)  
        self.grid()
        self.name_list = ["Thorin","Tyler","Jose","Bryson","Joe"]
        self.create_widget()

    def create_widget(self):
        self.lbl = Label(self)
        self.lbl["text"] = "Click to spin"
        self.lbl["font"] = ("Arial", 24) 
        self.lbl.grid()

        self.bttn = Button(self)
        self.bttn["text"]= "Spin"
        self.bttn["command"] = self.spin
        self.bttn.grid()

    def spin(self):
        if self.name_list:
            for i in range(5):
                index = random.randrange(len(self.name_list))
                self.lbl["text"] = self.name_list[index]
                self.lbl.grid()
            self.name_list.pop(index)
        else:
            self.lbl["text"] = "No more names"
            self.lbl.grid()

def main():
    root = Tk()
    root.title("Click Counter")
    root.geometry("600x600")

    app = Application(root)

    root.mainloop()

if __name__ == '__main__':
    main()

这是与GUI编程相关的一类非常常见的问题。问题的核心是窗口图形管理器。只要您的函数正在执行,图形管理器就会被冻结;在函数结束之前,更新标签文本不会产生明显的效果。因此,如果你有一个
for
循环,里面有一个
sleep(1)
命令,那么它所能做的就是将所有内容冻结五秒钟,然后在函数最终结束时用你的最终值进行更新

解决方法是使用
after
方法,它告诉Tkinter在将来的某个时候调用指定的函数。与睡眠不同,这为图形管理器提供了更新窗口所需的喘息空间

一种可能的方法是在之后用
注册六个事件:五个用于中间名称标签更新,一个用于最终名称更改和弹出

def spin(self):
    def change_name():
        index = random.randrange(len(self.name_list))
        self.lbl["text"] = self.name_list[index]
        self.lbl.grid()
    def finish_spinning():
        index = random.randrange(len(self.name_list))
        self.lbl["text"] = self.name_list[index]
        self.lbl.grid()
        self.name_list.pop(index)
    if self.name_list:
        name_changes = 5
        for i in range(name_changes):
            self.after(100*i, change_name)
        self.after(100*name_changes, finish_spinning)
    else:
        self.lbl["text"] = "No more names"
        self.lbl.grid()


(免责声明:这只是一个简单的示例,说明了在
之后如何使用
,可能不适合实际使用。特别是,如果在名称已经旋转时重复按“旋转”按钮,则可能会表现不好。此外,
更改名称
完成旋转
之间的代码重复非常难看)

由于每次都选择一个新的随机数,因此代码可以显示同一项目两次,因此会在同一时间选择相同的数字部分。请注意,直到循环结束后才会弹出,这意味着每次运行程序时,都会少一个名称,这可能是您想要的,也可能不是您想要的。如果希望列表保持相同大小和/或随机,则可以使用列表的副本。在列表上随机移动并按顺序显示已随机移动的列表。此外,您只需将标签网格化一次

class Application():
    def __init__(self, master):
        """ Initialize the frame. """
        self.master=master
        self.fr=Frame(master)
        self.fr.grid()
        self.name_list = ["Thorin","Tyler","Jose","Bryson","Joe"]
        self.ctr=0
        self.create_widget()

    def create_widget(self):
        self.lbl = Label(self.master width=30)
        self.lbl["text"] = "Click to spin"
        self.lbl["font"] = ("Arial", 24) 
        self.lbl.grid()

        self.bttn = Button(self.master)
        self.bttn["text"]= "Spin"
        self.bttn["command"] = self.spin
        self.bttn.grid()

    def change_label(self):
        self.lbl["text"] = self.name_list[self.ctr]
        self.ctr += 1
        if self.ctr < 5:
            self.master.after(1000, self.change_label)
        else:
            self.ctr=0

    def spin(self):
        if self.name_list and 0==self.ctr:  # not already running
            random.shuffle(self.name_list)
            self.change_label()
        else:
            self.lbl["text"] = "No more names"

if __name__ == '__main__':
    root = Tk()
    root.title("Click Counter")
    root.geometry("600x600")

    app = Application(root)

    root.mainloop()
class应用程序():
定义初始(自我,主):
“”“初始化帧。”“”
self.master=master
self.fr=帧(主)
self.fr.grid()
self.name_list=[“Thrin”、“Tyler”、“Jose”、“Bryson”、“Joe”]
self.ctr=0
self.create_小部件()
def创建_小部件(自):
self.lbl=标签(self.master宽度=30)
self.lbl[“text”]=“单击旋转”
self.lbl[“font”]=(“Arial”,24)
self.lbl.grid()
self.bttn=按钮(self.master)
self.bttn[“text”]=“Spin”
self.bttn[“命令”]=self.spin
self.bttn.grid()
def更改_标签(自我):
self.lbl[“text”]=self.name\u列表[self.ctr]
self.ctr+=1
如果self.ctr<5:
self.master.after(1000,self.change_标签)
其他:
self.ctr=0
def自旋(自):
如果self.name_列表和0==self.ctr:#尚未运行
随机.shuffle(self.name\u列表)
self.change_标签()
其他:
self.lbl[“text”]=“没有其他名称”
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=Tk()
root.title(“单击计数器”)
根部几何形状(“600x600”)
app=应用程序(根)
root.mainloop()

谢谢。这个答案非常有效,至少对于我正在做的一个小演示来说。因为我明天会给你,我感谢你及时的帮助。我将继续并将此标记为已回答。这是一个快速而肮脏的问题的快速而肮脏的解决方案:)也谢谢你的回答。碰巧我只想把剩下的名字翻个遍。否则我可能也会采纳你的建议。不过,我会将它们作为第二个示例保留在课堂上,因为我喜欢在单个程序上为我的示例进行变体,而不是全新的示例。所以,投票吧!