在PYQT中,有时我们会需要将log信息等实时打印到ui控件上,但是由于PYQT的进程保护机制,我们无法像使用print函数中那样,直接使用就能打印出来信息。所以通常都会发现,PYQT中的UI控件,比如QTextBrowser,使用它的append()函数和print函数同时来打印信息,往往print会将信息实时一点点打印出来,而QTextBrowser则不会,反而会等到这一段程序运行结束后,一次性把所有信息打印出来。
前面的描述有点绕,再简述一下:PYQT中在控件(比如QTextBrowser)上无法像print函数那样实时打印信息,而是会在程序段结束后,一次性全部打印上去。
在网上查找资料后,看到了解决方案:http://bbs.csdn.net/topics/390478497
注:那个帖子有点老了,有些程序也许运行不通,我只是根据里面给的自己修改的。
import sys
from PyQt4 import QtGui,QtCore
import time
import random
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
def run_(self, message):
#time.sleep(random.random() * 5)
self.trigger.emit(message)
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.text_area = QtGui.QTextBrowser()
self.thread_button = QtGui.QPushButton('Start threads')
self.thread_button.clicked.connect(self.start_threads)
central_widget = QtGui.QWidget()
central_layout = QtGui.QHBoxLayout()
central_layout.addWidget(self.text_area)
central_layout.addWidget(self.thread_button)
central_widget.setLayout(central_layout)
self.setCentralWidget(central_widget)
self.threads = MyThread(self)
self.threads.trigger.connect(self.update_text)
self.thread_no = 0
def start_threads(self):
self.thread_no += 1
message = "cnt:{0}".format(self.thread_no)
self.threads.run_(message) # start the thread
print(message)
def update_text(self, message):
# self.text_area.append('thread # %d finished'%thread_no)
# print('thread # %d finished'%thread_no)
self.text_area.append(message)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainWindow = Main()
mainWindow.show()
sys.exit(app.exec_())
前面给出了完整程序,这里捡几个要点说明一下:
trigger = QtCore.pyqtSignal(str)
创建一个信号trigger,传输字符串类型的数据。
def run_(self, message):
self.trigger.emit(message)
在线程类中另外定义的一个函数,主要就是调用trigger的emit函数(向trigger这个通道的入口灌水)。
self.threads = MyThread(self)
self.threads.trigger.connect(self.update_text)
创建线程类的实例,并将信号trigger连接到槽函数update_text。
def update_text(self, message):
# self.text_area.append('thread # %d finished'%thread_no)
# print('thread # %d finished'%thread_no)
self.text_area.append(message)
定义槽函数update_text,在控件上打印信息(前面定义了信号传输的是str,所以这里直接打印)。
自己正好碰到了这个问题,所以就记录一下,以便以后查阅。
吐槽:最近总碰到人在博客上问我为什么程序跑不通之类的问题,我也不知道你的环境是什么样的,少了什么依赖项,请自行解决,我只能尽力保证在自己的电脑上运行通过,能力有限请见谅。