wxPython多线程界面卡死或在不同平台崩溃问题
生活随笔
收集整理的這篇文章主要介紹了
wxPython多线程界面卡死或在不同平台崩溃问题
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、測試程序界面
?
二、不使用多線程代碼如下(當(dāng)點擊開啟日志的時候,直接導(dǎo)致界面卡死)
#coding:utf-8 import sys import threading import time import wxclass MyWindow():def __init__(self):self.app = Noneself.frame = Noneself.logObj = Noneself.main()def main(self):self.app = wx.App()self.frame = wx.Frame(None, -1, title='線程安全測試', size=wx.Size(1100, 700))self.createMainPanel()def show(self):self.frame.Show()self.app.MainLoop()def createMainPanel(self):mainPanel = wx.Panel(self.frame)startButton = wx.Button(mainPanel, label="啟動", pos=(5, 5))openLogButton = wx.Button(mainPanel, label="開啟日志", pos=(95, 5))closeLogButton = wx.Button(mainPanel, label="關(guān)閉日志", pos=(180, 5))self.logTextCtr = wx.TextCtrl(mainPanel, size=wx.Size(1000, 500), pos=(5,50),style=wx.TE_MULTILINE)self.frame.Bind(wx.EVT_BUTTON, lambda evt, textArea=self.logTextCtr: self.startBut(evt,self.logTextCtr),startButton)self.frame.Bind(wx.EVT_BUTTON, lambda evt: self.startLog(evt),openLogButton)self.frame.Bind(wx.EVT_BUTTON, lambda evt: self.closeLog(evt),closeLogButton)def startBut(self,evt,textArea):self.logObj = LogPrint(textArea)def startLog(self,evt):self.logObj.toPrint()def closeLog(self,evt):self.logObj.setIsPrint(0)class LogPrint():def __init__(self,textArea):self.isPrint = 0self.textArea = textAreadef toPrint(self):self.isPrint = 1i = 0while self.isPrint == 1:j = str(i) + " this is log!"self.textArea.WriteText(j + "\n")i = i + 1time.sleep(1)def setIsPrint(self,data):self.isPrint = dataif __name__ == "__main__":MyWindow().show()三、使用threading多線程后,界面不會卡死,在windows下運行啟動后界面可正常操作不會阻塞;但是在linux或mac下面點擊開啟日志后程序直接崩潰,代碼如下:
#coding:utf-8 import sys import threading import time import wxclass MyWindow():def __init__(self):self.app = Noneself.frame = Noneself.logObj = Noneself.main()def main(self):self.app = wx.App()self.frame = wx.Frame(None, -1, title='線程安全測試', size=wx.Size(1100, 700))self.createMainPanel()def show(self):self.frame.Show()self.app.MainLoop()def createMainPanel(self):mainPanel = wx.Panel(self.frame)startButton = wx.Button(mainPanel, label="啟動", pos=(5, 5))openLogButton = wx.Button(mainPanel, label="開啟日志", pos=(95, 5))closeLogButton = wx.Button(mainPanel, label="關(guān)閉日志", pos=(180, 5))self.logTextCtr = wx.TextCtrl(mainPanel, size=wx.Size(1000, 500), pos=(5,50),style=wx.TE_MULTILINE)self.frame.Bind(wx.EVT_BUTTON, lambda evt, textArea=self.logTextCtr: self.startBut(evt,self.logTextCtr),startButton)self.frame.Bind(wx.EVT_BUTTON, lambda evt: self.startLog(evt),openLogButton)self.frame.Bind(wx.EVT_BUTTON, lambda evt: self.closeLog(evt),closeLogButton)def startBut(self,evt,textArea):self.logObj = LogPrint(textArea)def startLog(self,evt):threadObj = threading.Thread(target=self.dolog, args=())threadObj.start()#self.logObj.toPrint()def dolog(self):self.logObj.toPrint()def closeLog(self,evt):self.logObj.setIsPrint(0)class LogPrint():def __init__(self,textArea):self.isPrint = 0self.textArea = textAreadef toPrint(self):self.isPrint = 1i = 0while self.isPrint == 1:j = str(i) + " this is log!"self.textArea.WriteText(j + "\n")i = i + 1time.sleep(1)def setIsPrint(self,data):self.isPrint = dataif __name__ == "__main__":MyWindow().show()四、解決卡死或不同平臺崩潰問題(使用wxpython中CallAfter自帶多線程,以及pubsub進行線程之間消息通訊來實現(xiàn))
python3多線程threading功能強大,結(jié)合jion()和setDaemon()函數(shù)使用更靈活,使用多線程時首先想到了threading, 但wxpython是用python寫的一個UI框架,其本身自帶有多線程函數(shù):
- wx.PostEvent
- wx.CallAfter
- wx.CallLater
其中,wx.CallLater是最抽象的線程安全函數(shù),其次是callAfter,最后是PostEvent。舍去這三個,直接使用threading導(dǎo)致UI出現(xiàn)卡頓,卡死等情況。結(jié)合wxpython自帶的多線程函數(shù)效果很好。
pubsub模塊中,pub.subscribe 可以理解為注冊一個接收消息的方法;pub.sendMessage 可以理解為發(fā)送消息給上一步注冊的方法
實現(xiàn)代碼:
#coding:utf-8import sys import threading import timeimport wx from wx.lib.pubsub import pubclass MyWindow():def __init__(self):self.app = Noneself.frame = Noneself.logObj = Noneself.main()def main(self):self.app = wx.App()self.frame = wx.Frame(None, -1, title='線程安全測試', size=wx.Size(1100, 700))self.createMainPanel()def show(self):self.frame.Show()self.app.MainLoop()def createMainPanel(self):mainPanel = wx.Panel(self.frame)startButton = wx.Button(mainPanel, label="啟動", pos=(5, 5))openLogButton = wx.Button(mainPanel, label="開啟日志", pos=(95, 5))closeLogButton = wx.Button(mainPanel, label="關(guān)閉日志", pos=(180, 5))self.logTextCtr = wx.TextCtrl(mainPanel, size=wx.Size(1000, 500), pos=(5,50),style=wx.TE_MULTILINE)self.frame.Bind(wx.EVT_BUTTON, lambda evt, textArea=self.logTextCtr: self.startBut(evt,self.logTextCtr),startButton)self.frame.Bind(wx.EVT_BUTTON, lambda evt: self.startLog(evt),openLogButton)self.frame.Bind(wx.EVT_BUTTON, lambda evt: self.closeLog(evt),closeLogButton)pub.subscribe(self.updateDisplay, "update")def startBut(self,evt,textArea):self.logObj = LogPrint()def startLog(self,evt):threadObj = threading.Thread(target=self.dolog, args=())threadObj.start()def dolog(self):self.logObj.toPrint()def updateDisplay(self, msg):t = msgself.logTextCtr.WriteText(t + "\n")def closeLog(self,evt):self.logObj.setIsPrint(0)class LogPrint():def __init__(self):self.isPrint = 0def toPrint(self):self.isPrint = 1i = 0while self.isPrint == 1:j = str(i) + " this is log!"wx.CallAfter(pub.sendMessage, "update", msg=j)print(j)i = i + 1time.sleep(1)def setIsPrint(self,data):self.isPrint = dataif __name__ == "__main__":MyWindow().show()?
?
總結(jié)
以上是生活随笔為你收集整理的wxPython多线程界面卡死或在不同平台崩溃问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue通过eventBut实现组件全局通
- 下一篇: 使用vuex 进行组件之间的通讯