請仔細閱讀我的問題 - 我知道有很多方法可以在Tkinter上實作倒計時而不凍結視窗,但所有現有的解決方案都會導致代碼的非阻塞。對于我的用例,我需要安排一個任務,在時間結束后自動運行,同時保持GUI處于活動狀態(不凍結)。我的猜測是,我需要以某種方式阻止下一個任務的執行,但這也會凍結GUI視窗。那么有沒有什么辦法呢?
到目前為止,我所擁有的是:
root = Tk.Tk()
def countdown(time, msg='Counting down') 。
def tick()。
nonlocal時間
status(f'{msg} ({60 - time}sec)' )
time = 1
root.after(1000, tick)
其中status()只是一個更新一些按鈕文本的函式。
目前的倒計時功能本身并不作業,因為我沒有辦法在超時后停止after()。
程式的其他部分將是:
countdown(10) # I need this line to be blocking or somehow prevents the code from going to next line.
print('starting scheduled job...'/span>)
作業()
我曾嘗試使用執行緒,但正如我之前所說的,這導致了代碼的非阻塞性,當我使用Thread.join()時,整個GUI又凍結了。
uj5u.com熱心網友回復:
目前,你的問題對我來說并沒有什么意義。根據我的理解,你希望你的job()函式在倒計時后被呼叫。
為此使用執行緒是不必要的。你可以直接使用after,一旦計時器達到0,就呼叫 下面是一個最小的例子 uj5u.com熱心網友回復: 注意:我可能想多了,另一個答案實際上可能更簡單一些 根據我的理解,你想創建一個程式,在一定時間后運行另一個任務,但任務和倒計時都不應該干擾GUI(但任務必須只在倒計時后運行),在代碼注釋中解釋:
標籤: 上一篇:型別錯誤:只能將str(而不是"int")串聯到str上
下一篇:K8snginxingresscontroller:error:errorparsingdeploy-tls-termination.yaml:errorconvertingYAMLtoJSON
job()/code>函式。
import tkinter as tk
def job()。
status.config(text="starting job")
def countdown(time, msg='counting down')。
時間 -= 1 f'{msg}({time}sec)')
if time != 0:
root.after(1000, countdown, time)
else:
job() # if job is blocking then create a thread.
root = tk.Tk()
status = tk.Label(root)
status.pack()
countdown(20)
root.mainloop()
# import what is needed。
from tkinter import Tk, Button, Label
from threading import Thread
from queue import Queue, Empty
import時間
# 該按鈕將呼叫的函式以開始倒計時。
# 和之后的任務。
def start_countdown()。
# disable button so not to accidentally run the task again.
# 在它還沒有開始之前。
button.config(state='disabled')
#創建一個佇列物件。
queue = Queue()
update_label(queue)
# set daemon=True to kill thread if the main thread exits[/span]。
Thread(target=countdown, args=(queue, ), daemon=True).start()
#你想在倒計時后做的任務。
def do_task() 。
for _ in range(10)。
print('doing task...' )
time.sleep(0.5)
# 實際的倒計時(btw使用`time.sleep()`更精確)。
# 而且只有執行緒會睡覺)。
# 把資料放在佇列中,以便于訪問。
#來自主執行緒的資料
def countdown(queue)。
seconds = 10
for i in range(1, seconds 1) 。
queue.put(f'Seconds left: {seconds 1 - i}')
time.sleep(1)
queue.put('Starting task')
# 放置一個哨兵來告訴讀取部分。
# 它可以停止。
queue.put('done')
#做任務,這將在同一個執行緒中運行。
# 這樣它就不會阻塞主執行緒。
do_task()
# 函式用于更新顯示用戶還剩多少秒的標簽。
def update_label(queue)。
try:
# since block=False it will raise an exception.
# if nothing is in queue.
data = queue.get(block=False)
except Empty: # 因此,除了它并簡單地傳遞。
pass
else。
# if no error was raised check if data is sentinel,.
# 如果是,停止這個回圈并啟用按鈕(如果需要)。
if data == 'done'/span>:
button.config(state='normal')
return: button.config(state="hljs-string">'normal)
# otherwise just update the label with data in the queue[/span]。
label.config(text=data)
finally:
# 和(幾乎)不管發生什么(沒有什么應該)再次回圈這個程序。
root.after(100, update_label, queue)
# basic tkinter設定
root = Tk()
root.geometry('300x200')
button = Button(root, text='Start countdown', command=start_countdown)
button.pack(expand=True)
label = Label(root)
label.pack(expand=True)
root.mainloop()
