Tkinter GUI多進程間通信與顯示刷新【mutiprocessing、threading、psutil】


Tkinter作為一個純GUI不具備類似Qt、MFC等框架的消息傳遞能力,只能通過Tkinter類對象對顯示值進行更新;

開發GUI程序一定是避免不了多線程和多進程的開發,當需要對運行進程靈活控制如暫停和恢復,則需引入庫psutil進行進程的掛起和恢復,至於多進程threading,根本不支持這些操作;

當Tkinter GUI需要與進程進行通信並刷新界面時,則需要去接受來自進程的消息,使用mutiprocessing提供的PiPe管道即可,由於接收是阻塞的,於是需要分立一個線程去接收,為什么不用進程?進程間對象空間不一致,若用共享內存就不能進行復雜的對象傳遞,而線程是處於同一個對象空間內的;

GUI_Flush

負責數據接收與界面刷新
 
注意設置線程和進程的守護進程和線程,不然退出GUI時會有線程或者進程殘留無法全部退出;

class Window:

對應功能界面顯示與刷新

class T_main:

對應信息發送與后台程序的執行

附Code如下;

import multiprocessing
import threading
import time
import tkinter as tk
import psutil

class Window:
    def __init__(self) -> None:
        self.win=tk.Tk()
        self.Var_Label = tk.StringVar(self.win,"INIT")
        self.Var_Button=tk.StringVar(self.win,"Start")
        self.ppp=multiprocessing.Pipe()
        #博客園:https://www.cnblogs.com/hardfood/ bili:崩析
    def GUI_Design(self):
        tk.Label(self.win,textvariable=self.Var_Label).grid(column=0,row=0)
        tk.Button(self.win,textvariable=self.Var_Button,command=self.multiprocess_run).grid(column=1,row=0)
        #博客園:https://www.cnblogs.com/hardfood/ bili:崩析
    def GUI_Flush(self):
        while True:
            data = self.ppp[1].recv()
            self.Var_Label.set(data)
        #博客園:https://www.cnblogs.com/hardfood/ bili:崩析
    def run(self):
        self.GUI_Design()
        tr=threading.Thread(target=self.GUI_Flush)
        tr.setDaemon(True)
        tr.start()
        self.win.mainloop()
        #博客園:https://www.cnblogs.com/hardfood/ bili:崩析
    def multiprocess_run(self):
        if self.Var_Button.get()=="Start":
            test_run = T_main(self.ppp[0])
            tr=multiprocessing.Process(target=test_run.run)
            tr.daemon=True
            tr.start()
            self.p = psutil.Process(tr.pid)
            self.Var_Button.set("Pause")
        elif self.Var_Button.get()=="Pause":
            self.p.suspend()
            self.Var_Button.set("Resure")
        elif self.Var_Button.get()=="Resure":
            self.p.resume()
            self.Var_Button.set("Pause")
        #博客園:https://www.cnblogs.com/hardfood/ bili:崩析
class T_main:
    def __init__(self,pip:multiprocessing.Pipe()[0]) -> None:
        self.pip = pip  
    #博客園:https://www.cnblogs.com/hardfood/ bili:崩析  
    def run(self):
        count=0
        while True:
            self.pip.send(str(count))
            count+=1
            time.sleep(1)
    #博客園:https://www.cnblogs.com/hardfood/ bili:崩析
if __name__=="__main__":
    xe = Window()
    xe.run()

運行效果如下;

 

關於Pyintsaller 多進程打包多個窗口問題

需在程序運行前加入函數 

multiprocessing.freeze_support()
大概意思是,linux和windows系統底層實現不同,
linux想創建新的進程直接fork()出子進程就行,
而windows則是直接創建出一個新進程來模擬子進程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM