[問題] Tkinter 用 after 模擬彈出視窗卡住

作者: jakeasa123 (啊斑斑)   2020-02-10 10:32:34
近日寫了一個小程式,
期望功能是可以連接到我自己的資料庫,
定時確認特定資料表的幾個欄位最新的數值並顯示出來。
程式運作的期望流程是:
1. 連線資料庫並抓取當下最新的資料
2. 用 after 每隔 5 秒呼叫確認資料的函式
3. 若檢查到資料有更新時,使用 lift 把模擬彈出視窗的物件拉到頂層
  原本想用彈出視窗,但發現不時彈出來有點麻煩,所以改 lift 圖片和 label 來模擬
4. lift 呈現 3 ~ 5 秒後,lower 這些模擬用物件使之消失
5. 繼續進行 (2) 步驟
目前測試起來,
連線資料庫與抓資料沒問題、
抓好資料後更新顯示的 label 沒問題、
lift 與 lower 獨立運作沒問題、
用 after 每隔 5 秒呼叫確認資料的函式沒問題,
但如果結合讓模擬的彈出視窗呈現數秒就會卡住(目前我這邊也是用 after)。
def 更新資料:
// 更新資料的過程
if 新資料有變動:
模擬用物件.lift()
after(3000, 模擬物件lower的函式)
after(5000, 更新資料)
(抱歉程式不在手邊沒辦法直接貼)
上述這樣子運作時,
程式進了 if 內的 after 會整個卡住且會有「沒有回應」的訊息,
但過了 if 內的 3 秒,
資料顯示還是可以正常運作(但模擬彈出視窗就完全看不見了)。
想過不要用 after 來呼叫 lower,
而是用一個 flag 來確認有沒有需要 lift 或 lower,
但這樣子的 lift 或 lower 會跟著 after(5000, 更新資料) 這行動作,
一次若有數個欄位更新時,
就沒辦法逐一顯示,
只會顯示最後一個更新的欄位。
現階段小弟想到的解決辦法是延續上段的方法,
但要用模擬彈出視窗的資料轉用 list 保存,
每次都檢查 list 內有沒有資料,
有資料就 lift 並將 list[0] 的資料呈現後刪除。
想請教這種情形下有沒有更合適的解法?
在此先謝謝各位前輩花費時間閱讀了,感謝!
作者: poototo (poototo)   2020-02-10 13:01:00
純經驗分享,覺得tinker似乎效能不佳?也有用tk的一些控制項來想辦法顯示資料處理的進度爬蟲,db,檔案等IO存取...少量以為OK,大量一下子就卡
作者: stucode   2020-02-10 19:16:00
檢查看看「模擬物件lower的函式」那裡有沒有執行什麼長時間操作。一般會卡到沒有回應表示你程式的某部分占用了GUI 主迴圈的執行緒。把它提出來放到另一個執行緒處理。如果找不到就先做 profiling 確認 call graph。也可以看看是不是有把 after(1,foo) 寫成 after(1,foo())
作者: jakeasa123 (啊斑斑)   2020-02-11 10:40:00
謝謝兩位前輩建議,小弟再確認一下

Links booklink

Contact Us: admin [ a t ] ucptt.com