戳人痛处

导航

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则是直接创建出一个新进程来模拟子进程

posted on 2021-12-30 17:17  戳人痛处  阅读(1904)  评论(0编辑  收藏  举报