簡體   English   中英

初始化 tkinter gui 導致主線程不在主循環中

[英]Initializing tkinter gui leads to main thread not in main loop

我的問題是關於初始化用 tkinter 構建的 GUI。 我正在 GUI 中啟動另一個線程,該線程正在運行一個需要 10 分鍾才能完成的腳本。 我在另一個線程中這樣做的原因是能夠在這 10 分鍾內保持 GUI 響應。

現在我正在嘗試執行以下操作(簡化)

   import tkinter as tk
   from threading import Thread
   class GUI:
        def __init__(self):
            self.master = tk.Tk()
            self.master.geometry("1400x700")
            // 
            ...
            //
            self.master.mainloop()
        
        def run_long_script(self): # Called by button in GUI
            self.t1 = Thread(target = long_script)
            self.start()

        def long_script(self):
            try:
                ...
            except InterruptedError as error:
    GUI()

這工作正常,但是當我嘗試關閉運行long_script的 GUI 時,我收到錯誤消息main thread not in main loop 我應該如何設計代碼才能正確關閉程序?

Tkinter像許多其他 GUI 一樣只能在主線程中使用小部件
(或者更確切地說,在運行mainlooop線程中)。

其他線程必須更新全局值(在線程之間共享)或使用queue將值發送到主線程。 主線程必須使用after(milliseconds, function_name)來定期運行函數,該函數將從全局變量或queue獲取值並更新進度條。


最少的工作代碼。

import threading
import time
import tkinter as tk
import tkinter.ttk as ttk

# --- functions ---

def long_script():
    global progress_value
    
    for i in range(20):
        print('loop:', i)
        
        # update global variable
        progress_value += 5
        
        time.sleep(.5)

def run_long_script():
    global progress_value
    global t
    
    if t is None: # run only one thread
        # set start value
        progress_value = 0
        # start updating progressbar
        update_progressbar()
        # start thread
        t = threading.Thread(target=long_script)
        t.start()
    else:
        print('Already running')
        
def update_progressbar():
    global t
    
    # update progressbar
    pb['value'] = progress_value
    
    if progress_value < 100:
        # run it again after 100ms
        root.after(100, update_progressbar)
    else:
        # set None so it can run thread again
        t = None
        
# --- main ---

# default value at start
progress_value = 0  
t = None

# - gui -

root = tk.Tk()

pb = ttk.Progressbar(root, mode="determinate")
pb.pack()

b = tk.Button(root, text="start", command=run_long_script)
b.pack()

root.mainloop()

暫無
暫無

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

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