PyQt Qthread 输出到textBrowser

maniachhz 2013-06-03 01:19:17
我的main()程序已经写好,输出大部分是print 输出.
我现在想使用PyQt 的Qthread, 当点击开始按钮时,main()执行过程中的信息实时输出到textBrowser ,

请问如何connect?

在网上找到一个例子,但我还是转不过弯来实现我想要的功能. 麻烦使用过的指点下?谢谢.

import sys
from PyQt4 import QtGui, QtCore
import time
import random


class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal(int)

def __init__(self, parent=None):
super(MyThread, self).__init__(parent)

def setup(self, thread_no):
self.thread_no = thread_no

def run(self):
time.sleep(random.random()*5) # random sleep to imitate working
self.trigger.emit(self.thread_no)


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)

def start_threads(self):
self.threads = [] # this will keep a reference to threads
for i in range(10):
thread = MyThread(self) # create a thread
thread.trigger.connect(self.update_text) # connect to it's signal
thread.setup(i) # just setting up a parameter
thread.start() # start the thread
self.threads.append(thread) # keep a reference

def update_text(self, thread_no):
self.text_area.append('thread # %d finished' % thread_no)

if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)

mainwindow = Main()
mainwindow.show()

sys.exit(app.exec_())


...全文
1665 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
The_Third_Wave 2013-12-26
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/390679483 求解答!
maniachhz 2013-06-14
  • 打赏
  • 举报
回复
引用 6 楼 panghuhu250 的回复:
[quote=引用 5 楼 maniachhz 的回复:] 比如说,我有个ping IP 的函数, 如何输出该函数的执行过程?
把ping函数放到你的pyqt代码中。

import sys
from PyQt4 import QtGui, QtCore
import time
import random
import subprocess
  
class MyThread(QtCore.QThread):
    trigger = QtCore.pyqtSignal(str) # trigger传输的内容是字符串
  
    def __init__(self, parent=None):
        super(MyThread, self).__init__(parent)
  
    def run(self):
        time.sleep(random.random()*5)  # random sleep to imitate working
        self.ping_host("http://www.yahoo.com")
    
    # 把下面代码中的print改为trigger.emit
    def ping_host(self, host):
        subprocess.call(['arp', '-d'], shell=True, stdout=open('NUL', 'w'), stderr=subprocess.STDOUT)
        # print('Pinging  ' + host + u', Please waiting...')
        self.trigger.emit('Pinging  ' + host + u', Please waiting...\n')
        for i in range(70):
            returncode = subprocess.call('ping -n 1 -w 1 %s' % host, shell = True, stdout = open('NUL', 'w'), \
                                         stderr = subprocess.STDOUT)
            if returncode != 0 :
                self.trigger.emit('.')
                # sys.stdout.write('.')
                # sys.stdout.flush()
                time.sleep(1)
                continue
            else:
                # print('OK')
                self.trigger.emit('OK\n')
                return
        # print(u'\t\n\nCannot connect ' + host +  '!')
        self.trigger.emit(u'\t\n\nCannot connect ' + host +  '!\n')

  
  
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)
  
    def start_threads(self):
        self.threads = []              # this will keep a reference to threads
        thread = MyThread(self)    # create a thread
        thread.trigger.connect(self.update_text)  # connect to it's signal
        thread.start()             # start the thread
        self.threads.append(thread) # keep a reference
  
    def update_text(self, message):
        self.text_area.insertPlainText(message) # use insertPlainText to prevent the extra newline character
  
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
  
    mainwindow = Main()
    mainwindow.show()
  
    sys.exit(app.exec_())
[/quote] 还有一个问题想请教,原ping_host函数如果无法连接主机,程序就中止执行,而不会再继续往下执行,
print(u'\t\n\nCannot connect ' + host +  '!')
sys.exit()
请问在PyQt里如何实现?需要自定义一个异常,然后再raise吗?
maniachhz 2013-06-04
  • 打赏
  • 举报
回复
引用 3 楼 panghuhu250 的回复:
[quote=引用 2 楼 maniachhz 的回复:] 但例子self.text_area.append 需要传递具体参数给它,而我的主程序main()里面是大部分print语句, 所以不知道如何传递给self.text_area.append,让主程序执行过程的信息输出到textBroser
print语句的功能是灌水,对应的是emit的部分,把print换成emit就行了。 另一个办法(可能有未知的危险!!)是重新定义print(要python3才行,python2中print是statement),这样已有的print的调用就不用改了。

def print(s):
  trigger.emit(s)
[/quote] 我还是没太明白emit, 我使用的是python2, 能否举个例子说明? 比如说,我有个ping IP 的函数, 如何输出该函数的执行过程?
    def ping_host(host):
        subprocess.call(['arp', '-d'], shell=True, stdout=open('NUL', 'w'), stderr=subprocess.STDOUT)
        print('Pinging  ' + host + u', Please waiting...'),
        for i in range(70):
            returncode = subprocess.call('ping -n 1 -w 1 %s' % host, shell = True, stdout = open('NUL', 'w'), \
                                         stderr = subprocess.STDOUT)
            if returncode != 0 :
                sys.stdout.write('.')
                sys.stdout.flush()
                time.sleep(1)
                continue
            else:
                print('OK')
                return
        print(u'\t\n\nCannot connect ' + host +  '!')
        sys.exit()
手无护鸡之力 2013-06-04
  • 打赏
  • 举报
回复
引用 7 楼 wn0112 的回复:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
import sys, subprocess, time

class myThread(QtCore.QThread):
	def __init__(self):
		QtCore.QThread.__init__(self)
		
	def run(self):
		self.pipe = subprocess.Popen('ping 127.0.0.1', stdout=subprocess.PIPE)

		while self.pipe.poll() == None:
			self.emit(QtCore.SIGNAL("getLog(QString)"), QtCore.QString.fromUtf8((self.pipe.stdout.readline().rstrip())))
			time.sleep(0.2)

		restInfo = self.pipe.stdout.readlines()
		if len(restInfo):
			for line in restInfo:
				self.emit(QtCore.SIGNAL("writeLog(QString)"), QtCore.QString.fromUtf8((line.rstrip())))

class MainWindow(object):
	def __init__(self, Dialog):
		self.bt = QtGui.QWidget(Dialog)
		Dialog.setMinimumWidth(400)
		Dialog.setMinimumHeight(300)
		self.button = QtGui.QPushButton(self.bt)
		self.button.setText('Start')
		self.button_2 = QtGui.QPushButton(self.bt)
		self.button_2.setText('Stop')
		self.text = QtGui.QPlainTextEdit(self.bt)
		self.text.setFont(QtGui.QFont('Courier New', 10))
		self.verticalLayout = QtGui.QVBoxLayout(Dialog)
		self.verticalLayout.addWidget(self.button)
		self.verticalLayout.addWidget(self.button_2)
		self.verticalLayout.addWidget(self.text)
		
		self.th1 = myThread()

		QtCore.QObject.connect(self.th1, QtCore.SIGNAL("getLog(QString)"), self.writeLog)
		QtCore.QObject.connect(self.button, QtCore.SIGNAL('clicked()'), self.run)
		QtCore.QObject.connect(self.button_2, QtCore.SIGNAL('clicked()'), self.stop)
	

	def run(self):
		self.th1.start()
	
	def stop(self):
		self.th1.pipe.terminate()
	
	def writeLog(self, str):
		self.text.appendPlainText(str)
	
app = QtGui.QApplication(sys.argv)
dlg = QtGui.QDialog()
main = MainWindow(dlg)		
dlg.show()
sys.exit(app.exec_())

所有的getLog改成writeLog
手无护鸡之力 2013-06-04
  • 打赏
  • 举报
回复

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
import sys, subprocess, time

class myThread(QtCore.QThread):
	def __init__(self):
		QtCore.QThread.__init__(self)
		
	def run(self):
		self.pipe = subprocess.Popen('ping 127.0.0.1', stdout=subprocess.PIPE)

		while self.pipe.poll() == None:
			self.emit(QtCore.SIGNAL("getLog(QString)"), QtCore.QString.fromUtf8((self.pipe.stdout.readline().rstrip())))
			time.sleep(0.2)

		restInfo = self.pipe.stdout.readlines()
		if len(restInfo):
			for line in restInfo:
				self.emit(QtCore.SIGNAL("writeLog(QString)"), QtCore.QString.fromUtf8((line.rstrip())))

class MainWindow(object):
	def __init__(self, Dialog):
		self.bt = QtGui.QWidget(Dialog)
		Dialog.setMinimumWidth(400)
		Dialog.setMinimumHeight(300)
		self.button = QtGui.QPushButton(self.bt)
		self.button.setText('Start')
		self.button_2 = QtGui.QPushButton(self.bt)
		self.button_2.setText('Stop')
		self.text = QtGui.QPlainTextEdit(self.bt)
		self.text.setFont(QtGui.QFont('Courier New', 10))
		self.verticalLayout = QtGui.QVBoxLayout(Dialog)
		self.verticalLayout.addWidget(self.button)
		self.verticalLayout.addWidget(self.button_2)
		self.verticalLayout.addWidget(self.text)
		
		self.th1 = myThread()

		QtCore.QObject.connect(self.th1, QtCore.SIGNAL("getLog(QString)"), self.writeLog)
		QtCore.QObject.connect(self.button, QtCore.SIGNAL('clicked()'), self.run)
		QtCore.QObject.connect(self.button_2, QtCore.SIGNAL('clicked()'), self.stop)
	

	def run(self):
		self.th1.start()
	
	def stop(self):
		self.th1.pipe.terminate()
	
	def writeLog(self, str):
		self.text.appendPlainText(str)
	
app = QtGui.QApplication(sys.argv)
dlg = QtGui.QDialog()
main = MainWindow(dlg)		
dlg.show()
sys.exit(app.exec_())

panghuhu250 2013-06-04
  • 打赏
  • 举报
回复
引用 5 楼 maniachhz 的回复:
比如说,我有个ping IP 的函数, 如何输出该函数的执行过程?
把ping函数放到你的pyqt代码中。

import sys
from PyQt4 import QtGui, QtCore
import time
import random
import subprocess
  
class MyThread(QtCore.QThread):
    trigger = QtCore.pyqtSignal(str) # trigger传输的内容是字符串
  
    def __init__(self, parent=None):
        super(MyThread, self).__init__(parent)
  
    def run(self):
        time.sleep(random.random()*5)  # random sleep to imitate working
        self.ping_host("http://www.yahoo.com")
    
    # 把下面代码中的print改为trigger.emit
    def ping_host(self, host):
        subprocess.call(['arp', '-d'], shell=True, stdout=open('NUL', 'w'), stderr=subprocess.STDOUT)
        # print('Pinging  ' + host + u', Please waiting...')
        self.trigger.emit('Pinging  ' + host + u', Please waiting...\n')
        for i in range(70):
            returncode = subprocess.call('ping -n 1 -w 1 %s' % host, shell = True, stdout = open('NUL', 'w'), \
                                         stderr = subprocess.STDOUT)
            if returncode != 0 :
                self.trigger.emit('.')
                # sys.stdout.write('.')
                # sys.stdout.flush()
                time.sleep(1)
                continue
            else:
                # print('OK')
                self.trigger.emit('OK\n')
                return
        # print(u'\t\n\nCannot connect ' + host +  '!')
        self.trigger.emit(u'\t\n\nCannot connect ' + host +  '!\n')

  
  
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)
  
    def start_threads(self):
        self.threads = []              # this will keep a reference to threads
        thread = MyThread(self)    # create a thread
        thread.trigger.connect(self.update_text)  # connect to it's signal
        thread.start()             # start the thread
        self.threads.append(thread) # keep a reference
  
    def update_text(self, message):
        self.text_area.insertPlainText(message) # use insertPlainText to prevent the extra newline character
  
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
  
    mainwindow = Main()
    mainwindow.show()
  
    sys.exit(app.exec_())
redstoneleo 2013-06-03
  • 打赏
  • 举报
回复
要传入string的话,QtCore.pyqtSignal(str)就OK了 self.threads = [] 这句可有可无,顺便后面的self.threads.append(thread)去掉也没关系 self.text_area.append接受的是str呀,这个方法继承自 QTextEdit.append (self, QString text)
panghuhu250 2013-06-03
  • 打赏
  • 举报
回复
引用 2 楼 maniachhz 的回复:
但例子self.text_area.append 需要传递具体参数给它,而我的主程序main()里面是大部分print语句, 所以不知道如何传递给self.text_area.append,让主程序执行过程的信息输出到textBroser
print语句的功能是灌水,对应的是emit的部分,把print换成emit就行了。 另一个办法(可能有未知的危险!!)是重新定义print(要python3才行,python2中print是statement),这样已有的print的调用就不用改了。

def print(s):
  trigger.emit(s)
maniachhz 2013-06-03
  • 打赏
  • 举报
回复
引用 1 楼 panghuhu250 的回复:
相关的代码共有4部分,你可以根据需要把他们放到你的程序的相关部分: 第8行:
trigger = QtCore.pyqtSignal(int)
作用:trigger将是main与该thread交流的通道。其中int是这个通道中可以传输的数据类型,还可以用其他的类型,如QtCore.pyqtSignal(type(""))(通道可以传输string)。 第40行:
thread.trigger.connect(self.update_text)  # connect to it's signal
作用:把trigger这个通道的出口连到update_text函数。 第44行:
def update_text(self, thread_no)
作用:实现update_text函数,这个例子里是把信息输出到一个文本框。 第18行:
self.trigger.emit(self.thread_no)
作用:向trigger这个通道的入口灌水。
谢谢. 其实我大概理解该例子的意思, 但例子self.text_area.append 需要传递具体参数给它,而我的主程序main()里面是大部分print语句, 所以不知道如何传递给self.text_area.append,让主程序执行过程的信息输出到textBroser
panghuhu250 2013-06-03
  • 打赏
  • 举报
回复
相关的代码共有4部分,你可以根据需要把他们放到你的程序的相关部分: 第8行:
trigger = QtCore.pyqtSignal(int)
作用:trigger将是main与该thread交流的通道。其中int是这个通道中可以传输的数据类型,还可以用其他的类型,如QtCore.pyqtSignal(type(""))(通道可以传输string)。 第40行:
thread.trigger.connect(self.update_text)  # connect to it's signal
作用:把trigger这个通道的出口连到update_text函数。 第44行:
def update_text(self, thread_no)
作用:实现update_text函数,这个例子里是把信息输出到一个文本框。 第18行:
self.trigger.emit(self.thread_no)
作用:向trigger这个通道的入口灌水。

37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧