基于multiprocessing和threading实现非阻塞的GUI界面显示
=========================================================
环境:python2.7、pyqt4、eric16.11热点:multiprocessing、threading、GUI、pyqt
需求:
希望界面上的QTextEdit控件可以滚动刷新日志,且软件界面不可以有阻塞。
=========================================================
郑重提示:如欲转载,请注明出处。
最终实现效果如下:
该实现的核心思想是:
先建立一个pipe,write端传给子进程,子进程无限发数据,read端传给子线程,在子进程活动的情况下无限取数据;子线程中再把read到的数据写入QTextEdit控件上。下面贴上详细的代码:
Ui_qt_main.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'F:\workspace\pyqt5\gui_thread_pipe_subprocess\qt_main.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.textEdit = QtGui.QTextEdit(self.centralwidget)
self.textEdit.setObjectName(_fromUtf8("textEdit"))
self.verticalLayout.addWidget(self.textEdit)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.horizontalLayout.addWidget(self.pushButton)
spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.verticalLayout.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "star", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
mainWindow.py
#-*- coding: utf-8 -*-
#mainWindow.py
from PyQt4 import QtCore, QtGui
from Ui_qt_main import Ui_MainWindow
from handleSubprocess import HandleSubProcess
import multiprocessing, threading
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
#联动按键
self.btnStar = "star"
self.btnStop = "stop"
self.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.buttonOn)
pass
def buttonOn(self):
if self.btnStar == self.pushButton.text():
self.pushButton.setText(self.btnStop)
self.starRun()
pass
elif self.btnStop == self.pushButton.text():
self.stopRun()
self.pushButton.setText(self.btnStar)
pass
pass
def stopRun(self):
print "stopRun"
if self.p.is_alive():
self.p.terminate()
self.t1.join(1)
pass
pass
def starRun(self):
#print "starRun"
parent_conn, child_conn = multiprocessing.Pipe()
#子进程
self.p = HandleSubProcess(child_conn)
self.t1 = threading.Thread(target=self.run_thread, args=(parent_conn,self.p))
self.p.start()
self.t1.start()
pass
def run_thread(self, parent_conn, pp):
while pp.is_alive:
self.textEdit.append(parent_conn.recv())
self.delay()
pass
print "==== run_thread end ==================\n"
pass
def delay(self, timeout=9999999):
cnt = timeout
while cnt>0:
cnt -= 1
pass
pass
pass
handleSubprocess.py
#-*- coding: utf-8 -*-
#handleSubprocess.py
import multiprocessing
class HandleSubProcess(multiprocessing.Process):
def __init__(self, child_conn):
super(HandleSubProcess, self).__init__()
self.child_conn = child_conn
pass
def run(self):
cnt = 0
while True:
self.child_conn.send("handleSubprocess\t"+str(cnt))
cnt += 1
self.delay()
pass
pass
def delay(self, timeout=9999999):
cnt = timeout
while cnt>0:
cnt -= 1
pass
pass
pass
enterPoint.py
#-*- coding: utf-8 -*-
#enterPoint.py
import sys
from PyQt4 import QtCore, QtGui
from mainWindow import MainWindow
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
以此与同道中人共勉。