WxPython界面利用pubsub如何實(shí)現(xiàn)多線程控制
WxPython界面用pubsub實(shí)現(xiàn)多線程控制
用WxPython做界面時(shí), 如果數(shù)據(jù)操作時(shí)間比較長,會(huì)使 WxPython 界面處于假死狀態(tài),用戶體驗(yàn)非常不好。
WxPython是利用pubsub來完成消息的傳送。
下面提供一個(gè) WxPython界面利用pubsub 實(shí)現(xiàn)2個(gè)線程的控制的例子
實(shí)際使用, 只要修改WorkThread1、WorkThread2 里的 run 內(nèi)容 及 MainFrame 里的 updateDisplay 內(nèi)容即可。
在此基礎(chǔ)上,可以實(shí)現(xiàn)多線程。
Python 3.7.3 wxPython 4.0.6 Pypubsub 4.0.3
在此之前有個(gè)單線程及進(jìn)度條的例子,簡單需求可以參考這個(gè)
下面提供本文的代碼
# encoding: utf-8 """ @author: 陳年椰子 @contact: hndm@qq.com @version: 1.0 @project:test @file: wx_thread.py @time: 2022-3-24 15:34 說明 """ import wx from pubsub import pub from time import sleep import time import threading import sys from random import random # 線程調(diào)用耗時(shí)長代碼 class WorkThread1(threading.Thread): def __init__(self): """Init Worker Thread Class.""" threading.Thread.__init__(self) self.breakflag = False self.start() def stop(self): self.breakflag = True # 耗時(shí)長的代碼 def workproc(self): while True: if self.breakflag: pub.sendMessage("update", mstatus='查詢Thread中斷') sleep(2) break ts1 = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) t_sum = "查詢的結(jié)果" # print(ts1,t_sum) # 此處加的數(shù)據(jù)庫代碼 pub.sendMessage("update", mstatus='{}:查詢最后10個(gè)數(shù)據(jù)并匯總{}'.format(ts1, t_sum)) sleep(10) pub.sendMessage("update", mstatus='workdone') return "" def run(self): """Run Worker Thread.""" pub.sendMessage("update", mstatus='workstart') self.workproc() # 線程調(diào)用耗時(shí)長代碼 class WorkThread2(threading.Thread): def __init__(self): """Init Worker Thread Class.""" threading.Thread.__init__(self) self.breakflag = False self.start() def stop(self): self.breakflag = True # 耗時(shí)長的代碼 def workproc(self): while True: if self.breakflag: pub.sendMessage("update", mstatus='隨機(jī)數(shù)Thread中斷') sleep(2) break ts1 = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) t_info = "隨機(jī)數(shù){}".format(str(random())) # print(ts1, t_info) # 此處加的數(shù)據(jù)庫代碼 pub.sendMessage("update", mstatus='{}:產(chǎn)生{}'.format(ts1, t_info)) sleep(1) pub.sendMessage("update", mstatus='workdone') return "" def run(self): """Run Worker Thread.""" pub.sendMessage("update", mstatus='workstart') self.workproc() class MainFrame(wx.Frame): """ 簡單的界面 """ def __init__(self, *args, **kw): # ensure the parent's __init__ is called super(MainFrame, self).__init__(*args, **kw) self.SetSize(size=(600, 400)) # create a panel in the frame pnl = wx.Panel(self) # and put some text with a larger bold font on it self.st = wx.StaticText(pnl, label="分析工具 V 2022", pos=(25, 25)) self.st2 = wx.StaticText(pnl, label="提示", pos=(25, 80)) font = self.st.GetFont() font.PointSize += 2 font = font.Bold() self.st.SetFont(font) self.st2.SetFont(font) # create a menu bar self.makeMenuBar() self.gauge = wx.Gauge(self, range=100, size=(500, 20)) self.gauge.SetBezelFace(3) self.gauge.SetShadowWidth(3) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.st, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 0) sizer.Add(self.st2, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 0) sizer.Add(self.gauge, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 0) self.SetSizer(sizer) # and a status bar self.CreateStatusBar() self.SetStatusText("啟動(dòng)完成!") pub.subscribe(self.updateDisplay, "update") def makeMenuBar(self): """ A menu bar is composed of menus, which are composed of menu items. This method builds a set of menus and binds handlers to be called when the menu item is selected. """ # Make a file menu with Hello and Exit items fileMenu = wx.Menu() # The "\t..." syntax defines an accelerator key that also triggers # the same event # helloItem = fileMenu.Append(-1, "&Hello...\tCtrl-H", # "Help string shown in status bar for this menu item") self.startItem = fileMenu.Append(-1, "開始", "開始工作") self.stopItem = fileMenu.Append(-1, "停止", "中斷工作") fileMenu.AppendSeparator() self.exitItem = fileMenu.Append(-1, "退出", "退出") # Now a help menu for the about item helpMenu = wx.Menu() aboutItem = helpMenu.Append(-1, "關(guān)于", "WxPython 界面與線程通訊的例子") # Make the menu bar and add the two menus to it. The '&' defines # that the next letter is the "mnemonic" for the menu item. On the # platforms that support it those letters are underlined and can be # triggered from the keyboard. self.menuBar = wx.MenuBar() self.menuBar.Append(fileMenu, "工作") self.menuBar.Append(helpMenu, "信息") # Give the menu bar to the frame self.SetMenuBar(self.menuBar) self.stopItem.Enable(False) self.count = 0 # Finally, associate a handler function with the EVT_MENU event for # each of the menu items. That means that when that menu item is # activated then the associated handler functin will be called. self.Bind(wx.EVT_MENU, self.OnStart, self.startItem) self.Bind(wx.EVT_MENU, self.OnStop, self.stopItem) self.Bind(wx.EVT_MENU, self.OnExit, self.exitItem) self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem) def OnExit(self, event): """Close the frame, terminating the application.""" try: self.work1.stop() self.work2.stop() sleep(2) except: pass self.Close(True) sys.exit() def OnStart(self, event): self.work1 = WorkThread1() self.work2 = WorkThread2() def OnStop(self, event): self.work1.stop() self.work2.stop() def OnAbout(self, event): """Display an About Dialog""" wx.MessageBox("分析工具 v2019", "關(guān)于", wx.OK | wx.ICON_INFORMATION) def updateDisplay(self, mstatus): """ Receives data from thread and updates the display """ # print('pub display', mstatus) if mstatus.find("workstart") >= 0: self.SetStatusText('開始工作,代碼不提供中斷線程語句,請(qǐng)等待!') self.startItem.Enable(False) self.stopItem.Enable(True) self.exitItem.Enable(False) if mstatus.find("workdone") >= 0: self.SetStatusText('完成!') self.stopItem.Enable(False) self.startItem.Enable(True) self.exitItem.Enable(True) else: if mstatus.find("查詢")>=0: self.st.SetLabel(mstatus) else: self.st2.SetLabel(mstatus) # if mstatus.find(",") > 0 and mstatus.find("計(jì)算") >= 0: # mdata = mstatus.split(',') # # 示范 , 實(shí)際使用需要傳送進(jìn)度 # # print(int(mdata[0].replace('計(jì)算',''))) # g_count = int(mdata[0].replace('計(jì)算', '')) # self.gauge.SetValue(g_count) def test(): app = wx.App() frm = MainFrame(None, title='分析工具') frm.Show() app.MainLoop() if __name__ == "__main__": test()
運(yùn)行后, 點(diǎn)擊 工作-開始。 2個(gè)線程開始工作,直到點(diǎn)擊工作-結(jié)束
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
django中間件及自定義中間件的實(shí)現(xiàn)方法
中間件就是在目標(biāo)和結(jié)果之間進(jìn)行的額外處理過程,在Django中就是request和response之間進(jìn)行的處理,相對(duì)來說實(shí)現(xiàn)起來比較簡單,這篇文章主要介紹了django中間件以及自定義中間件?,需要的朋友可以參考下2023-06-06Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)與操作符的練習(xí)題集錦
Python的一些算法題目經(jīng)常能夠幫助我們鞏固對(duì)一些常用方法的記憶,這里我們整理了一份Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)與操作符的練習(xí)題集錦,需要的朋友可以參考下2016-07-07Pycharm沒有報(bào)錯(cuò)提示(誤觸ignore)的完美解決方案
這篇文章主要介紹了Pycharm沒有報(bào)錯(cuò)提示(誤觸ignore)的解決方案,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12R語言屬性知識(shí)點(diǎn)總結(jié)及實(shí)例
在本篇文章里小編給大家整理了一篇關(guān)于R語言屬性知識(shí)點(diǎn)總結(jié)及實(shí)例內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-03-03Python?OpenCV中常用圖片處理函數(shù)小結(jié)
在計(jì)算機(jī)視覺和圖像處理領(lǐng)域,OpenCV(Open?Source?Computer?Vision?Library)是一個(gè)非常強(qiáng)大和流行的開源庫,本文將介紹一些常用的OpenCV函數(shù),希望對(duì)大家有所幫助2024-03-03tensorflow2.0實(shí)現(xiàn)復(fù)雜神經(jīng)網(wǎng)絡(luò)(多輸入多輸出nn,Resnet)
這篇文章主要介紹了tensorflow2.0實(shí)現(xiàn)復(fù)雜神經(jīng)網(wǎng)絡(luò)(多輸入多輸出nn,Resnet),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03