我需要在python tkinter应用程序中减慢循环

Tho*_*idt 5 python tkinter delay

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

我们的想法是从列表中随机生成一个名称,显示它,然后在每次单击一个按钮时将其从列表中删除.

为了使它更有趣,我希望程序在选择最后一个之前显示几个名称.我为此使用了一个简单的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()
Run Code Online (Sandbox Code Playgroud)

Kev*_*vin 3

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

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

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

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()
Run Code Online (Sandbox Code Playgroud)

(免责声明:这只是一个如何使用的简单示例after,可能不适合实际使用。特别是,如果在名称已经旋转的情况下重复按“旋转”按钮,它可能会表现得很糟糕。此外,change_name和之间的代码重复finish_spinning相当难看)