PYQT中QThread输出到textBrowser

问题概述

在PYQT中,有时我们会需要将log信息等实时打印到ui控件上,但是由于PYQT的进程保护机制,我们无法像使用print函数中那样,直接使用就能打印出来信息。所以通常都会发现,PYQT中的UI控件,比如QTextBrowser,使用它的append()函数和print函数同时来打印信息,往往print会将信息实时一点点打印出来,而QTextBrowser则不会,反而会等到这一段程序运行结束后,一次性把所有信息打印出来。
前面的描述有点绕,再简述一下:PYQT中在控件(比如QTextBrowser)上无法像print函数那样实时打印信息,而是会在程序段结束后,一次性全部打印上去。
在网上查找资料后,看到了解决方案:http://bbs.csdn.net/topics/390478497
注:那个帖子有点老了,有些程序也许运行不通,我只是根据里面给的自己修改的。

解决思路

  1. 使用QThread创建一个新线程,在线程中定义一个信号trigger,使用emit函数向trigger中“灌水”;
  2. 定义槽函数update_text,将其与信号trigger连接,并接收emit函数送过来的信息(可以是字符串,也可以是int或是double),在槽函数中使用append函数打印出来。

完整程序

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,所以这里直接打印)。

运行结果

PYQT中QThread输出到textBrowser_第1张图片

后记

自己正好碰到了这个问题,所以就记录一下,以便以后查阅。

吐槽:最近总碰到人在博客上问我为什么程序跑不通之类的问题,我也不知道你的环境是什么样的,少了什么依赖项,请自行解决,我只能尽力保证在自己的电脑上运行通过,能力有限请见谅。

你可能感兴趣的:(Python)