最近在使用Pyqt来写一个小的软件。有一个功能需要用到多线程去访问主线程的QtGui.QLable控件来进行更新内容.发现会出现界面不更新或是长时间访问就会使程序异常的情况。下面是我以前写的例子:
lock = threading.Lock() def __dostart(self, rmid): count = 0 while self.flag: self.lock.acquire() count = random.randint(1, 1000) self.RollMessages[rmid].setText(_translate("start", str(count)+ "_" + str(rmid), None)) self.lock.release() time.sleep(0.05) def Start(self): self.flag = True Threads = [] for i in xrange(self.countRoll): tRoll = threading.Thread(target = self.__dostart, args=[i]) Threads.append(tRoll) for i in xrange(self.countRoll): Threads[i].start()
错误的方法大家不要去学习,这种方法是直接去更新主线程上的RollMessages的项,运行不久就会崩溃或有异常情况发生。
后来看一些资料说Pyqt是需要使用信号和槽来实现子线更新主线程上的GUI的。方法如下
class test(): roll_signal = QtCore.pyqtSignal(int, int)#声名信号 def __init__(self): self.roll_signal.connect(self.roll_Slot)#连接信号和槽 @QtCore.pyqtSlot(int, int)#实现槽 def roll_Slot(self, count, rmid): self.RollMessages[rmid].setText(_translate("start", str(count)+ "_" + str(rmid), None)) def retranslateUi(self): for i in xrange(self.countRoll): self.RollMessages[i].setText("0") lock = threading.Lock() def __dostart(self, rmid): count = 0 while self.flag: self.lock.acquire() count = random.randint(1, 1000) self.roll_signal.emit(count, rmid)#发射信号 self.lock.release() time.sleep(0.05) def Start(self): self.flag = True Threads = [] for i in xrange(self.countRoll): tRoll = threading.Thread(target = self.__dostart, args=[i]) Threads.append(tRoll) for i in xrange(self.countRoll): Threads[i].start()
上面的代码只是为了方便理解写的代码片段,不一定保证是可以执行的。