簡體   English   中英

用 Tkinter 等待一定的時間

[英]Waiting certain amount of time with Tkinter

我有一個 Tkinter 程序,我想暫停 3 秒。 time.sleep不起作用,並且after方法不完全符合我的要求。

這是一個示例代碼:

from Tkinter import *
def waithere():
    print "waiting..."
root = Tk()

print "1"
root.after(3000,waithere)
print "2"

root.mainloop()

output:

1
2
*3 seconds*
waiting...

我想要的 output:

1
waiting...
*3 seconds*
2

謝謝。

通常,讓 GUI 等待某事是一個非常糟糕的主意。 這並不意味着基於事件的程序如何工作。 或者更准確地說,GUI 已經處於永久等待狀態,您不想用自己的等待來阻止它。

話雖如此,tkinter 有辦法等到某些事情發生。 例如,您可以使用“等待”函數之一,例如wait_variablewait_windowwait_visibility

假設您希望waithere進行等待,您可以使用wait_variable進行等待,並after給定的時間after設置變量。

這是基於您的原始代碼的解決方案:

from Tkinter import *
def waithere():
    var = IntVar()
    root.after(3000, var.set, 1)
    print("waiting...")
    root.wait_variable(var)

root = Tk()

print "1"
waithere()
print "2"

root.mainloop()

使用這些方法的優點是您的代碼在等待時仍然能夠響應事件。

僅供將來參考,不要在Tkinter使用長循環或無限循環; 它們將阻止 UI 響應用戶事件(也稱為凍結)。 我學到的方法是使用after()函數定期更新字段。

after()函數創建一個警報回調,意思是在調用時(使用正確的參數)它將對目標方法的調用(在下面的示例中def update(self)與我們輸入的延遲一起排隊。您可以在class 退出循環。在__init__上創建,然后當設置為False時不再調用after()

這是創建一個繼承 Tkinter.Frame 的類以繼承功能的示例。

try:
    import tkinter as tk
except:
    import Tkinter as tk

import datetime


class DelayedUpdateUI(tk.Frame):
    def __init__(self, master=None, **kw):
        # Create widgets, if any.
        tk.Frame.__init__(self, master=master, **kw)
        self.timeStr = tk.StringVar()
        self.lblTime = tk.Label(self, textvariable=self.timeStr)
        self.lblTime.grid()
        # Call update to begin our recursive loop.
        self.update()

    def update(self):
        self.timeStr.set(datetime.datetime.now())
        # We use after( milliseconds, method_target ) to call our update
        # method again after our entered delay. :)
        self.after(1000, self.update)


if __name__ == '__main__':
    root = tk.Tk()
    DelayedUpdateUI(root).grid()
    root.mainloop()

基於布賴恩回答的建議:

我從基於事件的角度理解推薦的方式,但對我來說感覺不是很直觀。 每次需要時我都必須查找技巧。 因此,我創建了一個小的 mixin 類,使其更易於閱讀:

class TkWaitMixin:
    """Simple wait timer that makes Tk waiting functionality 
    more intiutive. Applies the recommended way according to
    https://stackoverflow.com/a/51770561/12646289.
    """
    def start_wait_timer(self, milliseconds):
        self.resume = tk.BooleanVar(value=False)
        self.master.after(milliseconds, self.resume.set, True)
        # Assume master attribute is available: 
        # https://stackoverflow.com/a/53595036/12646289
        
    def wait_on_timer(self):
        self.master.wait_variable(self.resume)

用法示例:

import tkinter as tk

class MyWindow(tk.Tk, TkWaitMixin):
    def __init__(self, master):
        self.master = master
        self.message_label = tk.Label('')
        self.message_label.pack(padx=50, pady=50)
        
    def show_message(self, message, milliseconds):
        self.start_wait_timer(milliseconds)
        self.message_label['text'] = message
        self.wait_on_timer()
        self.message_label['text'] = ''
        
root = tk.Tk()
mywin = MyWindow(master=root)
mywin.show_message('Hello world', 2000)
root.mainloop()

顯然,這僅在您在 tkinter 代碼中使用類時才有用。

您忘記在root.after(3000,waithere <<<<-)

from tkinter import *

def waithere():
    print("waiting...")
root = Tk()

print("1")
root.after(3000,waithere())
print("2")

root.mainloop()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM