在一个应用中,除了一个主线程外,往往还有其他一些线程同时在进行工作,比如可能一个线程负责采集数据,另外一些线程负责数据分析,转发,保存或者显示等等,这时候就可以在数据采集线程中将数据通过信号的形式发送到后续处理线程,后续线程实现相应的槽函数来处理数据分析、转发,保存和显示等等。
无论是在Qt中还是Windows系统中UI刷新,都要求在主线程里完成,否则就可能出现系统出错的问题。在Qt中,如果在别的线程中想对UI进行刷新,则可以通过信号与槽的方式来实现。比如我们有一个线程进行图像采集,使用一个部件进行图像显示,这种情况下就可以使用信号还传递采集数据,在主线程中完成显示。
在程序中,从QThread派生出一个子类MyThread, 作为一个计数器,每100毫秒,计数器加1,然后通过自定义信号将该计数发射出去,在主线程中,QLCDNumber液晶显示面板收到该计数后,将计数显示出来。点击开始按钮,计数器开始运行,点击结束,计数器停止运行,并恢复为0, 在程序退出前,使用CloseEvent来处理对线程的中断操作。完整代码如下:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout,
QPushButton, QLCDNumber)
class MyThread(QThread):
countChanged = pyqtSignal(int)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
self.count = 0
def resetCount(self):
self.count = 0
def run(self):
while True:
self.msleep(100)
self.count += 1
self.countChanged.emit(self.count)
class DemoThreadSignalSlot(QWidget):
def __init__(self, parent=None):
super(DemoThreadSignalSlot, self).__init__(parent)
# 设置窗口标题
self.setWindowTitle('实战PyQt5: 线程间使用信号与槽')
# 设置窗口大小
self.resize(360, 200)
self.initUi()
def initUi(self):
mainLayout = QVBoxLayout()
# 液晶数字显示
self.lcd = QLCDNumber()
mainLayout.addWidget(self.lcd)
self.btnStart = QPushButton('开始')
self.btnStart.setMinimumHeight(60)
self.btnStart.clicked.connect(self.onBtnStart)
mainLayout.addWidget(self.btnStart)
self.setLayout(mainLayout)
self.thread = MyThread(self)
self.thread.countChanged.connect(self.lcd.display)
self.start = False
def onBtnStart(self):
if not self.thread is None:
if self.start == False:
self.start = True
self.btnStart.setText('结束')
self.thread.start()
else:
self.start = False
self.btnStart.setText('开始')
if self.thread.isRunning:
self.thread.terminate()
self.thread.quit()
self.thread.resetCount()
self.lcd.display(0)
# 关闭时调用
def closeEvent(self, event):
if not self.thread is None:
if(self.thread.isRunning):
self.thread.terminate()
self.thread.quit()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DemoThreadSignalSlot()
window.show()
sys.exit(app.exec())
运行结果如下图:
线程间信号与槽的使用测试
喜欢本文内容就关注, 收藏,点赞,评论和转发。
联系客服