PyQt/PySide2 中的 信号与槽 (pyqtSignal/Signal) 、多线程 (QThread) 和 定时器 (Timer)

PyQT——多线程(QThread) PyQT5线程:多线程QThread前言一、应用场景二、使用多线程解决卡顿和假死第一种:线程锁(QMutex)第二种:信号(Signal) 前言 一、应用场景 在编写GUI界面中,通常用会有一些按钮,点击后触发事件,比如去下载一个文件或者做一些操作,这些操作会耗时,如果不能及时结束,主线程将会阻塞,这样界面就会出现未响应的状态,因此必须使用多线程来解决这个问题。 二、使用多线程 解决卡顿和假死 1.两个按钮,分别在控制台打印不同的内容,分别点击两个按钮后,控制台会依次打印内容,多次点击按钮,程序会先循环完上 阅读详情

写在前面

PyQt5 和 PySide2 的区别

他们背后原理的差别我就不细说了(我也不知道),你只要记住使用上基本差不多就行,网上搜索他们用法的时候,以哪个为关键词搜索都行吧,官网 给出了他们的差异,聚焦我们要讲的问题,在信号与槽机制和多线程机制上,他们的差别如下:

# PyQt5 引入线程类和信号
from PyQt5.QtCore import QThread, pyqtSignal

# PySide2 引入线程类和信号
from PySide2.QtCore import QThread, Signal # 注意区别就在于这里的信号是 Signal,和 PyQt5 不一样,而线程类是一样的

信号与槽

信号是一个载体,装着自定义类型的数据(例如下面的object),将数据传送到绑定(connect)的函数(连接槽)中(数据作为参数传入函数)

信号与槽的基本框架如下:

signal = pyqtSignal(object) # 自定义信号传送的数据类型为 object

signal.emit(object) # 发射信号 object,每发射一次,连接槽函数就执行一次

signal.connect(custom_function) # 信号绑定的连接槽函数

# 自定义的连接槽函数,传入的参数就是信号
def custom_function(object):
    pass

线程类

线程类用于实现函数并行执行,假如我在动态的画函数曲线的同时想显示已经画了多长时间,这个情况在串行下就不好实现,因为要等到函数曲线画完才能开始执行下面的函数,就不能实现同步了。

而且 PyQt5/PySide2 不支持 python 的多线程类 threading,会报错 QObject: Cannot create children for a parent that is in a different thread. 。

线程类的基本框架如下:

class NewThread(QThread):

    signal = pyqtSignal(object) # 自定义信号,其中 object 为信号承载数据的类型

    def __init__(self, parent=None):
        super().__init__()
        self.x = 0 # 线程中自定义变量

    # 线程内可自定义其他函数
    def custom_function(self):
		pass
    
    # new_thread = NewThread()
    # 通过 new_thread.start() 调用此 run() 函数
    def run(self):
        self.custon_function()
        self.signal.emit(self.x) # 发射信号
        
new_thread = NewThread()

new_thread.start() # 为线程分配资源,让它执行

# 下面两个都是停止执行,但我一般用第二个
new_thread.wait()
new_thread.terminate()

定时器

定时器顾名思义就是一个计时的东西,按照指定的时间间隔执行一次指定函数。

定时器的基本框架如下:

timer = QTimer() # 生成一个定时器

timer.timeout.connect(custom_function) # 将定时器和自定义函数绑定,每隔下面指定时间执行一次自定义函数。注意它一般在生成定时器时就指定了,不要和 start 同时调用,否则会绑定多个自定义函数,导致每隔一定时间同时执行多个绑定函数(我就是因为这个 bug 才被迫学了其他两个骚操作,奇怪现象在最后一个参考上,果然踩坑的不止我一个)

timer.start(interval) # interval 是没两次执行的时间间隔,interval 的单位是毫秒,例如 interva=1000 即间隔时间为1秒

timer.stop() # 停止定时器

示例

下面是我结合了上面3个工具写的小玩意儿:

在这里插入图片描述

左边是计时器,点击“开始”按钮,然后按钮变成了“结束”,左边开始计时,右边同时画出函数图像,运行过程中点击“结束”则结束运行。其中 timer 间隔为1秒,即每隔1秒刷新一次左侧界面,输出时间值。

完整示例代码

import sys
import pyqtgraph as pg # 画图的工具,安装方法:pip install pyqtgraph
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QThread, pyqtSignal, QTimer
import numpy as np

class PlotSin(QThread):

    signal = pyqtSignal(object) # 定义信号,self.y 是 numpy.array,所以信号数据类型为 object

    def __init__(self, parent=None):
        super().__init__()
        self.y = None
        self.phase = 0

    def sin(self):
        self.x = np.arange(0, 3.0, 0.01)
        self.y = np.sin(2 * np.pi * self.x + self.phase)
        self.phase += 0.1
        QThread.msleep(200) # 等待200毫秒

    def run(self):
        for _ in range(300):
            self.sin()
            self.signal.emit(self.y) # 向连接槽发射信号 self.y

class PlotSin_MainWindow(QDialog):

    def __init__(self):
        super().__init__()        
        self.initUI()
        self.clock_time = 0
        self.timer = QTimer(self) # 生成定时器
        self.timer.timeout.connect(self.clock) # 绑定计时函数 self.clock

    def initUI(self):           

        self.creatContorls("时间显示:")
        self.creatResult("函数绘制:")

        layout = QHBoxLayout()
        layout.addWidget(self.controlsGroup)
        layout.addWidget(self.resultGroup)
        self.setLayout(layout)
        self.beginButton.clicked.connect(self.clock_begin)
        self.setGeometry(300, 300, 600, 300)
        self.setWindowTitle('Plot Sine')
        self.show()

    def creatContorls(self,title):
        self.controlsGroup = QGroupBox(title)
        self.beginButton  = QPushButton("开始")
        numberLabel = QLabel("运行时间:")
        self.clockLabel = QLabel("")
        controlsLayout = QGridLayout()
        controlsLayout.addWidget(numberLabel, 0, 0)
        controlsLayout.addWidget(self.clockLabel, 0, 1)
        controlsLayout.addWidget(self.beginButton, 3, 0)
        self.controlsGroup.setLayout(controlsLayout)

    def creatResult(self,title):
        self.resultGroup = QGroupBox(title)
        self.guiplot = pg.PlotWidget()
        gridLayout = QGridLayout()
        gridLayout.addWidget(self.guiplot,0,2,2,3)
        self.resultGroup.setLayout(gridLayout)

    def clock_begin(self):
        if not self.timer.isActive():
            self.recorder_thread = PlotSin() 
            self.recorder_thread.signal.connect(self.displaySin) # 绑定信号槽函数
            self.recorder_thread.start() # 线程执行
            self.clock()
            self.timer.start(1000)
        else:
            self.beginButton.setText("开始")
            self.clockLabel.setText("")
            self.recorder_thread.terminate() # 终止线程
            self.timer.stop() # 终止定时器
            self.clock_time = 0
            text = str(self.clock_time) + "s"
            self.clockLabel.setText(text)

    def clock(self):
        text = str(self.clock_time) + "s"
        self.clockLabel.setText(text)
        if self.clock_time == 0:
            self.beginButton.setText("结束")
            
        self.clock_time += 1

    def plotSin(self, y):
        self.guiplot.clear()
        self.guiplot.plot(y)

    def displaySin(self, y):
        self.plotSin(y)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = PlotSin_MainWindow()
    window.show()
    sys.exit(app.exec_())

参考

  1. Differences Between PySide and PyQt/zh

  2. PySide/PyQt Tutorial: Creating Your Own Signals and Slots

  3. Pyqt5系列(八)-自定义信号

  4. QT信号槽机制

  5. PyQt5进阶(二)——多线程:QThread & 事件处理

  6. Is it possible to get an array from a thread in PyQt5?

  7. Pyside2 - Unexpected behaviour

【Python_PySide2学习笔记(九)】基于QThread实现子线程更新主线程/UI线程 基于QThread实现 子线程更新 主线程/UI线程。 阅读详情

相关推荐

(一)企业微信 - 会话内容存档

企业微信获取会话记录。

专打丶小豆豆的博客 2889

PySide2学习总结(八)Qt的信号(Signal)和槽(Slot)

前言 在GUI编程过程中,经常需要进行通信的处理,往往需要各种类型的对象之间进行通信,比如,当用户点击了某个按钮,我们希望它调用某个功能输出一些提示信息。 在其他编程工具中往往使用“回调”技术来实现对象之间的通信。“回调”是将函数的指针(地址)作为参数传递给另一个处理函数,并在该函数内利用这个参数来调用原函数。 简介 在Qt中使用信号和槽(Signals and Slots)来实现其他编程工具包的...

sinat_37623490的博客 2万+

拒绝无意义刷屏,打造高效率热点追踪,极空间部署『TrendRadar』

今天的这个项目确实不错,通过部署在极空间NAS之后,我们就能一直不间断的获取到自己想要看到的新闻或者信息。项目的设置项其实有很多,有兴趣的小伙伴可以在部署之后自己慢慢挖掘~目前年终大促正在火热进行中,极空间NAS不管是新品还是之前在售的畅销型号都有专属的优惠,并且还能叠加国补、平台优惠等福利,享受180天换新以及2年质保服务 ,更有抽奖、晒单等活动,喜欢的小伙伴赶快冲吧!

qq_63499861的博客 2290

PySide2 自定义信号

PySide2自定义信号与PyQt5中自定义信号差不多一样,只是PyQt5中的pyqtSignal变成了QtCore.Signal,用法还是一模一样。 import sys from PySide2 import QtCore from PySide2.QtWidgets import QDialog, QWidget, QVBoxLayout, QApplication, QPushBut...

只想整天学习 3976

抖音最新风控体系研究

小编从技术角度对抖音的风控史和落地目标,跟大家聊一聊抖音,包括海外版抖音TikTok的现状与生态。 1、非常非常早的时期,抖音刚出来的时候,没有任何封禁,这个阶段,导入一个开发库,加上一个请求头,咵咵咵的数据随便拿。 2、2018-2019年,抖音加入了设备id和xg机制,在绝大多数的接口中,携带了设备id参数,同时在请求头中加入了xg,如今的apk市场,能追溯到的最早xg是0200打头的,而小编见过的最早的xg是0000打头的。这个时期的接口,这些参数都还只是预设,没有实际的用处,设备随便写,

qq517348412的博客 1万+

从Chimera到ChimeraX:科研绘图升级指南,让你的论文配图更专业

本文详细介绍了从UCSF Chimera升级到ChimeraX的科研绘图指南,帮助研究者提升论文配图质量。ChimeraX在渲染引擎、大分子处理能力和动画功能上具有显著优势,特别适合生命科学和结构生物学领域。文章涵盖材质设置、专业配色、工作流程和期刊适配等核心技巧,助力产出出版级分子可视化图像。

weixin_33670786的博客 928

GUI编程--Qt--多线程

多线程,并发处理事务,提高效率;在Qt GUI 界面开发中使用多线程

weixin_45228198的博客 1621

如何浏览与下载全球免费的地图高分辨率(亚米级)的遥感影像?

前言 如果你想使用商业卫星的高分辨遥感影像,一般价格昂贵。我们可以使用地图平台上免费的高分辨率数据。目前数据源很多,比如说google earth、天地图、四维地球、必应地图等等。这些影像统一有一个共同点就是:RGB三波段;Web地图瓦片服务。这意味着我们可以通过瓦片服务下载影像,但下载的影像只有三个波段,分别是 一.引言 二、可使用高分辨率的地图数据源 1.Google Earth影像 2.Esri World Image 3.天地图 4.必...

锐多宝的地理空间 2万+

PyQt多线程显示视频:从界面卡死到流畅播放的完整方案

在Python GUI开发中,视频播放或摄像头画面实时显示常会遇到界面卡顿甚至无响应的难题,其根源在于耗时操作阻塞了主线程事件循环。理解事件循环与线程模型是解决此类问题的基础,多线程编程则提供了将重负载任务与UI渲染分离的可行路径。Python的GIL虽然限制了字节码并行,但OpenCV等底层库在I/O时会释放GIL,因此子线程负责视频帧读取与解码是可行的。但这需要遵守Qt框架的铁律:UI操作只能由主线程执行。借助QThread与Worker对象,配合信号槽机制实现线程安全通信,即可构建稳定高效的多线程视频

weixin_33937913的博客 386

python爬取淘宝数据

python爬取淘宝数据淘宝评论 淘宝评论 打开淘宝,选择打开需要爬取的商品的评论。在谷歌浏览器选择开发者工具,选择network,找到list_detail_rate.htm?itemId=624466733121,点击headers、previews,可以看见相应的评论数据。 爬取一页屏评论代码如下 import re import requests headers = { 'Referer': '在headers中', 'User-Agent': '在

qq_36333776的博客 5797

全新DEIM有效涨点改进目录 | 本专栏持续更新500+篇内容 | 包含各种顶会顶刊卷积、注意力、特征融合模块、有效特征聚合提取模块,上采样模块、下采样模块,二次创新模块、独家创新等几百种创新点改进

🚀【CVPR2025DEIM改进专栏速览】🔥 专栏提供500+篇目标检测创新改进方案,涵盖卷积/注意力/特征融合等创新改进点,均源自顶会论文及实战经验。支持多领域应用(工业/医疗/遥感等),配套完整教程和答疑服务。亮点包括: 1️⃣ 持续更新SOTA模型改进方案 2️⃣ 小白友好型实验操作指南 3️⃣ 跨学科科研支持(已助非计算机专业发表论文) 4️⃣ 提供虚拟环境配置方案。 订阅可获完整项目代码及交流群服务,适合研究生科研论文改进需求。价格呈上涨趋势,早订更优惠!

Ai缝合怪、助力小伙伴高效发论文 2041

PyQt6入门实战:从环境搭建到文件对话框的完整指南

Python凭借简洁的语法与丰富的生态,在数据处理和自动化脚本领域广受欢迎,但构建图形用户界面时,选择一款合适的GUI框架往往成为工程落地的关键。PyQt6作为Qt框架的Python绑定,以完备的控件库、高效的信号与槽机制以及出色的跨平台一致性,成为桌面应用开发的主流选择。理解信号与槽的解耦原理,能够有效分离业务逻辑与界面交互;掌握布局管理和事件处理机制,则可以让界面自适应调整并精准响应用户操作。本文从环境搭建入手,通过可直接运行的完整代码,系统演示了窗口创建、常用控件、布局管理、自定义信号、事件过滤器以及

weixin_33894640的博客 499

全国(山东、安徽)职业技能大赛--信息安全管理与评估大赛题目+答案讲解——windows应急响应篇

保护数据,捍卫安全,展现技能,赢得荣耀!全国职业技能大赛-信息安全与评估大赛,挑战你的技术,揭示黑客的秘密!加入我们,成为信息安全的守护者!

人若无名,便可专心练剑 906

PyQt5+pyqtgraph实现高性能动态连续波形图:从卡顿到流畅的实战指南

在Python GUI开发中,实时数据可视化是高频需求,动态波形图广泛用于串口调试、传感器监控、心电信号展示等场景。许多开发者习惯使用matplotlib,但在高频刷新时容易遭遇界面卡顿和CPU占用过高的问题。本文介绍PyQt5与pyqtgraph的组合方案:pyqtgraph基于numpy向量化计算与精简的GraphicsObject体系,通过setData方法高效更新曲线数据,配合QTimer定时刷新和采集线程,可轻松实现几十帧的流畅波形。文章还分享了固定坐标轴防闪烁、环形缓冲区、避免定时器重叠等工程经

weixin_34115824的博客 305

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

基于LattePanda构建一体化电子仪器平台:从架构设计到软硬件实现

电子测量仪器是工程师和爱好者进行电路调试、信号分析的核心工具。其基本原理是通过传感器和模数转换器(ADC)采集信号,再经由处理器进行运算、分析与显示。传统仪器功能单一、成本高昂,而软件定义仪器(SDI)技术通过软件编程实现硬件功能,提供了灵活、可定制的解决方案,在科研、教育及个人创客领域具有重要价值。本文聚焦于利用LattePanda单板计算机,结合高速数据采集卡、高精度DAC等硬件模块,通过模块化的软件架构设计,实现示波器、信号发生器、逻辑分析仪等多种仪器功能的一体化集成平台构建,详细阐述了其系统架构、关

weixin_34335458的博客 495

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

三、PyQtgraph Qtimer定时器的使用

在用PyQtgraph的时候,经常会使用到定周期操作,类似于多线程,广泛应用在显示,刷新,定周期查询等场景。 Qtimer是在PyQtgraph内部的定时器,所以不可避免的导入Qt库,不要忘记“app = pg.QtGui.QApplication([])” 1.代码如下: 功能是每隔1s打印一次“hello” import pyqtgraph as pg import time from time import perf_counter from ...

weixin_39888010的博客 1994

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

QT pyside2 线程嵌套子线程 实现开始运行和停止运行

QT pyside2 结合线程嵌套子线程 实现开启程序和停止程序

EXIxiaozhou的博客 984

PYQT5|Pyside2 后台线程 与 信号方式多线程防止界面卡死

PYQT5|Pyside2 后台线程 与 信号方式多线程防止界面卡死 界面阻塞问题 前面我们的练习里开发了一个类似 Postman 的HTTP接口测试工具。 其中,具体发送请求消息的代码如下 def sendRequest(self): method = self.ui.boxMethod.currentText() url = self.ui.editUrl.text() payload = self.ui.editBody.t

HRD的博客 2675

关于pyqt,pyside2信号与槽函数同步的问题

目前查阅了很多资料,有关c语言qt的解决方案很多,但还没看到python语言qt的解决方案,这里记录一下。发送出去后slot函数会在receiver所在的线程的event loop中进行处理。发送并不需要等待第一次发送后槽函数执行完毕。这样信号和槽函数就无法在时序上依次执行。可以看到信号很快全部发送完了,但槽函数还在慢慢一步一步执行。这样信号发送将和槽函数执行,在时序上严格一一对应。在connect()函数添加参数。这是pyqt的默认模式。这种连接模式需要自行设置。这是剩下的3种连接模式。

BraveNewWorld10的博客 472

PySide2多线程问题示例:创建新线程、子线程发射信号到主界面

PySide2多线程问题示例:创建新线程、子线程发射信号到主界面 本文是小白在pyside学习过程中的记录,从无子线程、子线程在主程序中直接操作Qt界面、子线程发射信号操作主界面三个步骤依次进阶,记录对多线程的一种处理方式。如有不合理的地方恳请路过大神赐教! 一、示例问题(随便整了一个简单的):创建一个界面,在一个界面输入最大最小值,在另一个界面依次打印出以下信息:从最小值开始,每次加1,到最大值后结束。 先给出三个方式的结果: 1、只有一个主程序:在操作界面填入信息,点击开始按钮后,无法再点击界面上其他任

xhzc7的博客 7336

Pyside2之QTimer

QTimer QTimer类提供了重复和单次的定时器,要使用定时器,需要先创建一个QTimer实例,将其Timeout信号连接到槽函数,并调用start(),然后,定时器,会以恒定的间隔发出timeout信号 当窗口的控件收到Timeout信号后,他就会停止这个定时器。QTimer常常用于更新QLabel图像等。 start(milliseconds) 启动或重新启动定时器,时间间隔为毫秒,如果定时器已经运行,他将停止并重新启动,如果singleSlot信号为真,定时器仅被激活一次 Stop() 停止定时器

qingqiqiuwhy的博客 3053

pyqt多线程操作

多线程是实现并发的一个重要手段。在GUI编程中,经常需要将耗费时间较多的任务分离出来成为一个线程,避免对主线程造成影响(造成界面无响应)。 在Qt中,最简单的多线程主要通过继承QThread类实现,重载虚函数run()。 1、一般我们先创建一个QThread子类,其中最主要的是run函数,当进程开始时会执行这个函数。 2、pyqtSignal()代表pyqt信号,我们在run的结束加一个结束退出信...

CloudCver 4007

Python Pyside2 多线程实现局域网IP扫描

利用pyside2实现带界面的局域网IP扫描工具

weixin_55423423的博客 748

pyside2使用Qthread停止工作的问题:Process finished with exit code -1073740791 (0xC0000409)

pyside2使用Qthread停止工作的问题 的解决方案

dcyywin8的博客 1630
上一篇: ubuntu 更新系统源
下一篇: top使用方法
二月七
博客等级 码龄12年 12粉丝 21原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值