多线程是实现并行处理的重要手段,在GUI编程中,经常需要将耗费任务分离,用单独的线程来处理,避免对主线程造成影响(最常见的影响就是会造成主界面无法响应的假死现象)。在Qt中,最常用的多线程一般是通过继承QThread类,重载其函数run()来实现。

QThread简介

QThread类提供了一种独立于平台的方式来管理线程。一个QThread对象管理程序中的一个控制线程。在run()中执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内部运行Qt事件循环。

可以使用QObject.moveToThread()的方式将工作对象移动到线程中执行。

class Worker (QObject):   resultReady = pyqtSignal(str)     def __init__(self, parent=None):       super(WorkerThread, self)._init__(parent)     def doWork(self, parameter):       result=''       #这里执行耗时的阻塞操作       self.resultReady.emit(result) class Controller(QObject):   operate=pyqtSignal(str)   def __init__(self, parent=None):       super(WorkerThread, self)._init__(parent)       worker = Worker()       self.workerThread =QThread()       worker.moveToThread(self.workerThread)       workerThread.finished.connect(worker.deleteLater)       self.operate.connect(worker.doWork)       worker.resultReady.connect(self.handleResults)       self.workerThread.start()     def __del__(self):       self.workerThread.quit()       self.workerThread.wait()    def handleResults(sel, result):       #在这里处理工作结束后返回的信息

然后, Worker中的doWork()代码将在单独的线程中执行。在这里我们可以将Worker的doWork()槽函数连接到来自任何线程的任何信号,因为借助Qt中的队列连接的机制,可以安全地跨线程连接信号和槽。

另外一种使用线程的方式就是继承QThread并重新实现其run() 函数。

class WorkerThread(QThread):   resultReady = pyqtSignal(str)     def __init__(self, parent=None):       super(WorkerThread, self).__init__(parent)    def run(self):       result=''       #这里执行耗时的阻塞操作       self.resultReady.emit(result)    def __del__(self):       self.quit()       self.wait() class MyObject(QObject):   ....   def startWorkInAThread(self):       workerThread = WorkerThread(self)       workerThread.resultReady.connect(self.handleResults)       workerThread.finished.connect(workerThread.deleteLater)       workerThread.start()    def handleResults(sel, result):       #在这里处理工作结束后返回的信息

QThread.Priority线程优先级枚举量:

  • QThread.IdlePriority (0): 仅在没有其他线程在运行时调度。
  • QThread.LowestPriority (1): 比LowPriority安排的时间少。
  • QThread.LowPriority (2): 比NormalPriority安排的时间少。
  • QThread.NormalPriority (3): 操作系统的默认优先级。
  • QThread.HighPriority (4): 比NormalPriority安排的时间更多。
  • QThread.HighestPriority (5): 比“高优先级”安排的时间更频繁。
  • QThread.TimeCriticalPriority (6): 尽可能频繁地安排。
  • QThread.InheritPriority (7): 使用与创建线程相同的优先级。这是默认值。

QThread常用函数:

  • usleep(usecs): 静态函数,强制当前线程休眠usecs微秒。
  • msleep(msecs): 静态函数,强制当前线程休眠msecs毫秒。
  • sleep(secs): 静态函数,强制当前线程休眠secs秒。
  • run(self): 在调用start之后,线程将调用此函数。QThread的默认实现只是调用exec()。
  • setPriority(self, priority: 'QThread.Priority'): 设置线程优先级。
  • priority(self): 返回线程的优先级设置。
  • start(self, priority: 'QThread.Priority'): 通过调用run()开始执行线程。操作系统将根据优先级参数调度线程。如果线程已经在运行,则此函数不执行任何操作。
  • wait(self): 阻塞线程,直到满足以下任一条件:1.与该QThread对象关联的线程已完成执行(即,从run()返回时)。如果线程完成,此函数将返回true。如果线程尚未启动,它也会返回true。2.执行期限已到达。如果到了最后期限,此函数将返回false。
  • quit(self): 告诉线程的事件循环以返回码0(成功)退出。等效于调用QThread.exit(0)。如果线程没有事件循环,则此函数不执行任何操作。
  • exit(self, returnCode: int): 告诉线程的事件循环以returnCode退出。
  • terminate(self): 终止线程的执行。根据操作系统的调度策略,线程可能会立即终止,也可能不会立即终止。可以在终止()之后使用QThread.wait()。当线程终止时,所有等待线程完成的线程都将被唤醒。警告:此功能很危险,不建议使用。线程可以在其代码路径中的任何位置终止。修改数据时可以终止线程。线程自身无法清除、解锁任何保持的互斥锁等。总之,仅在绝对必要时才使用此功能。
  • isRunnig(self): 线程正在运行返回True,否则返回False。
  • isFinished(self): 线程已结束返回True,否则返回False。

QThread常用信号:

  • finish(self): 线程在执行完成之前发出该信号。发出此信号时,事件循环已经停止运行。除了延迟的删除事件外,线程中将不再处理其他事件。该信号可以连接到QObject.deleteLater(),以释放该线程中的对象。

注意:如果关联的线程使用terminate终止线程,则不确定从哪个线程发出该信号。

注意:这是一个私有信号。它可以用于信号连接,但不能由用户发射。

  • started(self): 在调用run()函数之前,该信号在开始执行时从关联线程发出。

注意:这是一个私有信号。它可以用于信号连接,但不能由用户发射。

测试

测试代码在pyqt5-examples的线程样例代码基础上,演示了使用多线程绘制Mandelbrot分形图像。 完整代码如下:

import sysfrom PyQt5.QtCore import (Qt, pyqtSignal, QPoint, QSize,                          QMutex, QMutexLocker, QWaitCondition, QThread)from PyQt5.QtGui import QColor, QImage, QPainter, QPixmap, qRgbfrom PyQt5.QtWidgets import QApplication, QWidget #一些控制变量DefaultCenterX = -0.647011DefaultCenterY = -0.0395159DefaultScale = 0.00403897 ZoomInFactor = 0.8ZoomOutFactor = 1 / ZoomInFactorScrollStep = 20 #图像渲染线程class RenderThread(QThread):    ColormapSize = 512        #图像渲染完成后,发射这个信号    renderedImage = pyqtSignal(QImage, float)        def __init__(self, parent = None):        super(RenderThread, self).__init__(parent)                self.mutex = QMutex()        self.condition = QWaitCondition()        self.centerX = 0.0        self.centerY = 0.0        self.scaleFactor = 0.0        self.resultSize = QSize()        self.colormap = []                self.restart = False        self.abort = False                for i in range(RenderThread.ColormapSize):            self.colormap.append(self.rgbFromWaveLength(380.0 + (i * 400.0 / RenderThread.ColormapSize)))                def __del__(self):        self.mutex.lock()        self.abort = True        self.condition.wakeOne()        self.mutex.unlock()        self.wait()            def render(self, centerX, centerY, scaleFactor, resultSize):        locker = QMutexLocker(self.mutex)                self.centerX = centerX        self.centerY = centerY        self.scaleFactor = scaleFactor        self.resultSize = resultSize                if not self.isRunning():            self.start(QThread.LowestPriority)        else:            self.restart = True            self.condition.wakeOne()                def run(self):        while True:            self.mutex.lock()            resultSize = self.resultSize            scaleFactor = self.scaleFactor            centerX = self.centerX            centerY = self.centerY            self.mutex.unlock()                        halfWidth = resultSize.width() // 2            halfHeight = resultSize.height() // 2            image = QImage(resultSize, QImage.Format_RGB32)                        NumPasses = 8            curpass = 0                        # 渲染Mandelbort分形几何图像            while curpass = Limit:                                break                            numIterations += 1                            c = c*c + c0                            if abs(c) >= Limit:                                break                            numIterations += 1                            c = c*c + c0                            if abs(c) >= Limit:                                break                            numIterations += 1                            c = c*c + c0                            if abs(c) >= Limit:                                break                                                if numIterations = 380.0 and wave <= 440.0:            r = -1.0 * (wave - 440.0) / (440.0 - 380.0)            b = 1.0        elif wave >= 440.0 and wave <= 490.0:            g = (wave - 440.0) / (490.0 - 440.0)            b = 1.0        elif wave >= 490.0 and wave <= 510.0:            g = 1.0            b = -1.0 * (wave - 510.0) / (510.0 - 490.0)        elif wave >= 510.0 and wave <= 580.0:            r = (wave - 510.0) / (580.0 - 510.0)            g = 1.0        elif wave >= 580.0 and wave <= 645.0:            r = 1.0            g = -1.0 * (wave - 645.0) / (645.0 - 580.0)        elif wave >= 645.0 and wave <= 780.0:            r = 1.0         s = 1.0        if wave > 700.0:            s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0)        elif wave 

运行结果如下图:

测试QThread

本文知识点

  • 为什么要在程序中使用多线程。
  • 使用QThread的两种方法。
  • 使用多线程绘制耗时的几何图像。

前一篇: 实战PyQt5: 127-处理XML文档


请多多关注,评论,收藏,点赞,和转发。

qt 等待线程结束_实战PyQt5: 128-使用多线程进行并行处理相关推荐

  1. c++主线程等待子线程结束_简单明了的 Python 多线程来了 | 原力计划

    作者 | 万里羊责编 | 王晓曼出品 | CSDN博客线程和进程计算机的核心是CPU,它承担了所有的计算任务,就像是一座工厂在时刻运行.如果工厂的资源有限,一次只能供一个车间来使用,也就是说当一个车间 ...

  2. python等待线程结束_如何等待线程完成后再继续

    我需要在另一个线程中运行一个函数,并获取该函数的返回值以将其保存到主线程中的一个变量中.基本上,我的代码调用该函数,该函数通过串行端口与天平通信,等待并获取响应,解析响应,并以浮点形式返回响应.我需要 ...

  3. qt 等待线程结束_c – 停止Qt线程:调用exit()或quit()不会停止线程执行

    在main()即主线程中创建了一个QThread. 将一个worker类移动到新线程.该线程执行worker类的'StartThread'方法. 工人线程: //header file class W ...

  4. java 等待线程结束 框架_深入理解Java多线程与并发框架——线程的状态

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享!Java架构筑基​zhuanlan.zhihu.comJava架构筑基--专注于Java技术的研究与分享! 后续文章将首 ...

  5. chart.js 饼图显示百分比_实战PyQt5: 135-数据可视化之QChart绘制饼图

    饼图是数据可视图表的基本类型,在QChart中,QPieSeries, QPieSlice处理饼图的绘制. QPieSeries QPieSeries类以饼图形式显示数据.饼图系列由定义为QPieSl ...

  6. pyqt5 qwidget 边框_实战PyQt5: 116-画刷类QBrush

    QBrush简介 QBrush类定义由QPainter绘制的形状的填充图案.一个画刷可以有颜色,填充图案,渐变和纹理属性. 样式填充使用Qt.BrushStyle枚举变量定义填充图案.默认的填充样式为 ...

  7. qss qmenu 设置icon位置大小_实战PyQt5: 125-使用配置文件来保存和恢复应用的设置...

    在通常情况下,用户使用一个软件的时候,期望保存一些数据状态,比如窗口的大小和位置,主题,选项,最近操作过的文件等等信息,在下一次启动软件的时候就自动加载这些信息,让软件恢复到上一次退出时的状态.在Wi ...

  8. python判断线程结束_判断Threading.start新线程是否执行完毕的实例

    新写自己的Threading类 class MyThread(threading.Thread):#我的Thread类 判断流程结束没 用于os shell命令是否执行判断 def __init__( ...

  9. qchart 坐标轴设置_实战PyQt5: 156-QChart图表之更换图表主题

    图表主题 QChart定义了多种图表主题,可以创建不同风格的图表显示,在调整图表主题风格的时候,为了使整个应用的风格看起来更和谐一致,一般要使用应用程序的背景调色板来调整应用的颜色以适配图表所选的主题 ...

最新文章

  1. c#.net URL参数传递及在js中引用
  2. Custom Url Helper for Zend View
  3. VK1629A 驱动芯片
  4. RDIFramework.NET ━ 9.4 角色管理 ━ Web部分
  5. java 读取properties文件
  6. JS身份证合法性校验完全版
  7. 微软“抛弃”Edge 投入 Chromium 怀抱!
  8. ASP.NET RouteModule相关的一些东西
  9. 能被2、3、4、5、6、7、8、9、10、11、13、25整除的整数的特征是?有趣的21详解
  10. ce 修改 java游戏_CE6.4.3修改器加强版 CE加强版 可过NP的和众多游戏的CE修改器 - 下载 - 搜珍网...
  11. Mac OS 如何批量转换图片格式
  12. mysql 启动 spawn错误_supervisor ERROR (spawn error):错误解决
  13. 计算机网络谢希仁第七版课后习题答案(第七章)
  14. markdown转pdf
  15. 【P14】差分输入分立耳机放大器电路V22大改
  16. matlab求平均聚集系数,复杂网络聚类系数和平均路径长度计算的MATLAB源代码
  17. 超级经典,绝对好的第三方控件网
  18. 零成本学arduino教程——74hc165扩展寄存器教程
  19. 微信小程序checkbox被挤压变形解决办法
  20. 父亲节别忘了妈:带上全家去旅行

热门文章

  1. burp 代理的时候无法访问https网站
  2. php基础_变量和比较符
  3. jquery解析XML
  4. jQuery(一)—— jQuery 概述 / jQuery 选择器 / jQuery 样式操作 / jQuery 效果
  5. OpenCV3学习(2.1)——图像Mat数据的访问-at/ptr/iterator
  6. 7-168 币值转换 (20 分)
  7. 7-24 悄悄关注 (10 分)
  8. 7-19 树种统计 (10 分)
  9. datagridview 纵向 横向 合并单元格_每日一Excel技巧(熟能生巧):带公式的单元格,快速批量复制、填充...
  10. 缅因大学欧洛诺分校计算机科学,一分钟带大家了解美国名校缅因大学优势!