【PyQt学习篇 · ②】:QObject - 神奇的对象管理工具

news2025/1/18 7:37:12

文章目录

  • QObject介绍
  • Object的继承结构测试
  • QObject对象名称和属性
    • QObject对象名称和属性的操作
    • 应用场景
  • QObject父子对象
    • QObject父子对象的操作
  • QObject的信号与槽
    • QObject的信号与槽的操作

QObject介绍

在PyQt中,QObject是Qt框架的核心对象之一。QObject是一个基类,它提供了对象之间的信号和槽机制、父子对象关系管理、对象属性以及事件处理等功能。

以下是QObject类的一些常用特性和功能:

  1. 信号和槽机制:QObject支持信号和槽机制,用于实现对象之间的通信。通过定义信号和槽,可以在事件发生时触发、连接和处理功能。信号可以在特定条件下被发射,而槽则是处理信号的函数。

  2. 父子对象关系:QObject支持父子对象关系的管理。可以使用setParent()方法将一个QObject对象设置为另一个QObject对象的父对象。当父对象被销毁时,它会负责销毁其所有的子对象。

  3. 对象属性:QObject支持动态属性机制,可以通过setProperty()方法设置对象的属性值,并可以通过property()方法获取属性值。属性可以用于存储对象的状态或其他自定义信息。

  4. 事件处理:QObject提供了处理事件的基本机制。可以通过重写event()eventFilter()方法来处理对象接收到的事件。事件可以是鼠标事件、键盘事件或其他自定义事件。

  5. 对象生命周期管理:QObject对象在创建后可以自动管理其生命周期。在Python中,当一个QObject对象没有引用时,它会被Python的垃圾回收器销毁。同时,QObject的父子关系机制也可以在父对象销毁时自动销毁子对象。

QObject是PyQt中其他重要对象(如QWidget、QThread等)的基类,它为它们提供了共享的核心功能和特性。

下面,将从以下基本程序展开演示QObject的具体使用方法:

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QLabel的学习")
        self.resize(500, 500)
        
        self.setup_ui()
    
    # 调用以下文章自定义的函数
    def setup_ui(self):
        pass

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

    window = Window()
    window.show()

    sys.exit(app.exec_())

注意:

  • 在以上代码中,self代表当前实例化的Window对象。在Python中,通过使用self关键字,可以在类的方法中引用对象自身。

  • 在构造函数中的super().__init__()调用中,self被用于传递当前对象自身给父类的构造函数,确保父类的初始化操作能够正确地处理当前对象。

Object的继承结构测试

如以下代码所示,在Window()类中自定义一个QObject_Inheritance_Structure_Testing(self)方法,在该方法中,通过调用QObject.mro()方法,可以获取到QObject类的方法解析顺序。方法解析顺序决定了当一个方法被调用时,解释器在哪个类中找到该方法的定义。通过打印每个继承类,可以查看继承结构中各个类的排列顺序。

    # QObject继承结构测试
    def QObject_Inheritance_Structure_Testing(self):
        mros  = QObject.mro()
        for mro in mros:
            print(mro)

运行结果:

在这里插入图片描述
这些打印结果表示了QObject类的继承关系。QObject类继承自sip.wrapper类,sip.wrapper类又继承自sip.simplewrapper类,最后都继承自object类。继承结构定义了这些类之间的层次关系,使得QObject类可以具有基类和扩展类提供的功能和属性。

QObject对象名称和属性

在进行QObject对象的名称和属性操作时,可以使用以下 API:

  1. setObjectName(name): 设置对象的名称,可以用于在后续代码中查找和识别具体的对象。一般这个名称是唯一的,当做对象的ID来使用。
  2. objectName(): 获取对象的名称。
  3. setProperty(name, value): 设置对象的属性,可以用于存储和传递自定义的数据。
  4. property(name): 获取对象的属性值。
  5. dynamicPropertyNames(): 获取对象所有动态属性的名称列表。

QObject对象名称和属性的操作

以下将对演示如何使用这些API:

	# QObject对象名称和属性
    def Operation_of_QObject_object_names_and_attributes(self):
        # QObject的对象操作
        obj = QObject()
        obj.setObjectName("notice")     # 设置对象的名称
        print(obj.objectName())     # 打印对象的名称

        # QObject的属性操作
        obj.setProperty("notice_level", "error")    # 设置了notice_level属性,其值为error,同等于notice_level="error"
        obj.setProperty("notice_level2", "warning")

        print(obj.property("notice_level2"))     # 打印notice_level2属性的值
        print(obj.dynamicPropertyNames())   # 获取对象obj的所有动态属性名称列表并打印

运行结果:

在这里插入图片描述

应用场景

在本篇文章中,QObject对象名称和属性的主要演示的应用场景:用于qss的ID选择器,属性选择器,方便统一设置样式。

设置qss样式方法一:使用setStyleSheet()方法。

        label = QLabel(self)
        label.setText("Hello world")
        
        # 设置qss样式
        label.setStyleSheet("font-size: 20px; color: red;")

运行结果:

在这里插入图片描述
通过设置qss样式,将字体的大小变为20px,颜色变为红色。

设置qss样式方法二

  • 创建一个QObject.qss文件,在文件内写入对应的qss样式
QLabel#notice {
    font-size: 20px;
    color: red;
}

QLabel#notice[notice_level="warning"] {
    font-size: 30px;
    color: yellow;
}

在以上qss样式中,notice为对象的名称,notice_levelwarning为对象的属性及其值。

  • 编写使用该样式的程序
        with open("QObject.qss", "r") as f:
            qApp.setStyleSheet(f.read())    # 读取整个字符串并赋值给app全局变量

        label = QLabel(self)
        label.setText("Hellow world")
        label.setObjectName("notice")  # 设置对象名称,即ID

        label2 = QLabel(self)
        label2.move(100, 100)
        label2.setText("PyQt5")
        label2.setObjectName("notice")  # 设置对象名称,即ID
        label2.setProperty('notice_level', 'warning')   # 设置对象的属性及其值

        btn = QPushButton(self)
        btn.setText("我是按钮")
        btn.move(50, 50)

在以上代码中,打开名为QObject.qss的样式表文件,读取其中的内容,并将其应用于应用程序全局变量qApp。因为样式表文件中只设置了QLabel的样式,所以只会匹配QLabel对象,并根据对象的名称和属性匹配其样式。

运行结果:
在这里插入图片描述

QObject父子对象

在PyQt中,可以使用以下API来操作QObject的父子对象:

  1. setParent(parent): 将当前对象设置为指定父对象的子对象。当父对象被销毁时,所有的子对象也会被自动销毁。
  2. parent(): 返回当前对象的父对象。
  3. children(): 返回当前对象的直接子对象列表。
  4. findChild( type, objectName): 在当前对象的子对象中查找指定名称和类型的对象。如果找到,则返回该对象;否则返回 None。
  5. findChildren(type): 在当前对象的子对象中查找指定类型的所有对象并返回一个列表。

其中,findChildfindChildren方法是一些方便的查找子对象的API。findChild方法需要传入待查找对象的名称和类型作为参数;而findChildren方法只需要传入待查找对象的类型即可。这两个方法都只会查找当前对象的直接子对象,不会递归查找其子孙对象。

QObject父子对象的操作

尝试构造以下父子关系:

在这里插入图片描述

    # QObject父子对象的操作
    def QObject_Parent_Child_Object(self):
        # 创建五个QObject对象
        obj0 = QObject()
        obj1 = QObject()
        obj2 = QObject()
        obj3 = QObject()
        obj4 = QObject()
        obj5 = QObject()

        print('obj0', obj0)     # 打印obj0对象的地址
        print('obj1', obj1)
        print('obj2', obj2)
        print('obj3', obj3)
        print('obj4', obj4)
        print('obj5', obj5, '\n')

        obj1.setParent(obj0)    # 设置obj1的父对象为obj0
        obj2.setParent(obj0)    # 设置obj2的父对象为obj0
        print('obj0 children: ', obj0.children(), '\n')   # 查看obj0的直接子对象列表

        print('未修改父对象前,父对象:', obj2.parent())      # 未修改父对象前
        obj2.setParent(obj1)
        print('修改父对象后,父对象:', obj2.parent(), '\n')      # 修改父对象后

        print('obj0 children: ', obj0.children())  # 修改obj2的父对象后,查看obj0的直接子对象列表

        obj3.setParent(obj1)    # 设置obj3的父对象为obj1

        obj4.setParent(obj2)    # 设置obj4的父对象为obj2
        obj5.setParent(obj2)    # 设置obj5的父对象为obj2

在以上代码中,设置了两次obj2的父对象,第一次设置的父对象为obj0,第二次设置的父对象为obj1。

运行结果:

在这里插入图片描述
从运行结果可看出,一个对象,它的父对象只能有一个,且以最后设置的父对象为主。

再观察以下代码,学习findChild(objectName, type)findChildren(type)的使用:

    # QObject父子对象的操作
    def QObject_Parent_Child_Object(self):
        # 创建五个QObject对象
        obj0 = QObject()
        obj1 = QObject()
        obj2 = QObject()
        obj3 = QObject()
        obj4 = QObject()
        obj5 = QObject()

        print('obj0', obj0)     # 打印obj0对象的地址
        print('obj1', obj1)
        print('obj2', obj2)
        print('obj3', obj3)
        print('obj4', obj4)
        print('obj5', obj5, '\n')
        
        obj1.setParent(obj0)    # 设置obj1的父对象为obj0
        obj2.setParent(obj0)    # 设置obj2的父对象为obj0
        obj2.setObjectName("2")     # 设置obj2对象的名称为2

        obj3.setParent(obj1)    # 设置obj3的父对象为obj1

        obj4.setParent(obj2)    # 设置obj4的父对象为obj2
        obj5.setParent(obj2)    # 设置obj5的父对象为obj2

        print(obj0.findChild(QObject))  # 返回第一个子对象,即返回obj1的地址
        print(obj0.findChild(QObject, "2"))     # 获取obj0的QObject类型且对象名称为2的子对象
        print(obj0.findChild(QObject, "3"))     # 获取obj0的QObject类型且对象名称为3的子对象,没有时返回None

        print(obj0.findChildren(QObject))   # 获取obj0的所有QObject类型的子对象

运行结果:

在这里插入图片描述

QObject的信号与槽

在PyQt中,信号与槽(Signals and Slots)是一种用于实现对象间通信的机制。信号是由发送者发出的消息,而槽是接收信号并对其做出响应的方法。以下是PyQt中常用的信号与槽相关的API:

  1. 信号(Signal)相关的API:

    • pyqtSignal(): 创建一个自定义信号。
    • emit(): 发出信号,即调用信号对象的emit()方法。
  2. 槽(Slot)相关的API:

    • @pyqtSlot(): 将一个方法声明为槽函数。
    • connect(): 连接一个信号与一个槽函数。
    • disconnect(): 断开一个信号与一个槽函数的连接。
    • sender(): 返回发出信号的对象。
    • blockSignals(bool): 暂时阻塞或取消阻塞信号。
    • receivers(sign):返回连接到信号的接收器数量
  3. 信号与槽的连接相关的API:

    • QMetaObject.connectSlotsByName(self, obj): 通过对象的命名约定自动连接信号与槽函数。

QObject的信号与槽的操作

# QObject的信号与槽
def Signal_and_slot_of_QObject(self):
    self.obj = QObject()

    def destroy_slot(obj):
        print('对象被释放了', obj)

    def obj_name_slot(name):
        print('对象名称发生了改变', name)

    self.obj.objectNameChanged.connect(obj_name_slot)   # 建立与obj_name_slot槽函数的连接
    self.obj.destroyed.connect(destroy_slot)   # 建立与destroy_slot槽函数的连接

    self.obj.setObjectName('xxx')
    self.obj.objectNameChanged.disconnect()     # 取消连接
    self.obj.setObjectName('yyy')
    self.obj.objectNameChanged.connect(obj_name_slot)   # 再次建立与槽函数的连接
    self.obj.setObjectName('xxyy')

    self.obj.blockSignals(True)     # 临时阻断连接
    self.obj.setObjectName('111')
    self.obj.blockSignals(False)    # 重新连接
    self.obj.setObjectName('222')

    print(self.obj.receivers(self.obj.objectNameChanged))   # 获取objectNameChanged信号绑定的槽函数数量

    del self.obj

运行结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1145604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】STL容器适配器入门:【堆】【栈】【队列】(16)

前言 大家好吖,欢迎来到 YY 滴C系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! 目录 一.容器适配器的概念二.为什么stack和q…

Ubuntu Studio 23.10发布

导读Ubuntu Studio 是 Ubuntu 的多媒体社区版。该项目的 23.10 版本重点改进了 PipeWire 支持和音频配置。 PipeWire 已获得大量改进,包括针对专业音频和消费音频的修复。现在,JACK 兼容性可实时运行,一些 FireWire 功能也已实现。 我们还在…

Wpf 使用 Prism 实战开发Day01

一.开发环境准备 1. VisualStudio 2022 2. .NET SDK 7.0 3. Prism 版本 8.1.97 以上环境,如有新的版本,可自行选择安装新的版本为主 二.创建Wpf项目 1.项目的名称:MyToDo 项目名称:这里只是记录学习,所以随便命名都无所谓,只要觉得合理就…

sql-50练习题0-5

sql练习题0-5题 前言数据库表结构介绍学生表课程表成绩表教师表 0-1 查询"01"课程比"02"课程成绩高的学生的信息及课程分数0-2查询"01"课程比"02"课程成绩小的学生的信息及课程分数0-3查询平均成绩大于等于60分的同学的学生编号和学生…

2023年江西省“振兴杯”工业互联网安全技术技能大赛暨全国大赛江西选拔赛 Write UP

文章目录 一、协议分析 - modbus二、协议分析 - 异常的流量三、协议分析 - S7Error四、协议分析 - OmronAttack五、组态编程 - 工程的秘密六、组态编程 - 工程的秘密七、组态编程 - 简单的计算八、组态编程 - 交通灯九、组态编程 - 有趣的转盘十、应急处置 - 登录日志分析十一、…

DevOps与CI/CD的最佳实践

在当今的软件开发领域,DevOps(开发与运维的结合)和CI/CD(持续集成/持续交付)已经成为了不可或缺的一部分。它们不仅提高了软件开发的效率,还帮助团队更快地交付高质量的软件。本文将深入探讨DevOps文化和CI…

nodejs+vue+elementui+express外卖数据分析python

在上述需求分析的基础上,通过深入研究,将系统使用人员划分为信息采集编辑、信息维护编辑、信息发布编辑三个角色。 本论文的研究目的是为了给采编者提供一套完善、高效的智能信息收集解决方案,并利用一系列的程序设计与开发,为采…

Linux中shell脚本练习

目录 1.猜数字 2.批量创建用户 3.监控网卡Receive Transmit 数据的变化 4.部署Linux 5.系统性能检测脚本 6.分区脚本 7.数据库脚本 1.猜数字 随机数的生成 使用环境变量RANDOM,范围是0~32767 编写guest.sh,实现以下功能&#xff1…

AS/400简介

AS400 AS400 简介AS/400操作系统演示 AS400 简介 在 AS400 中,AS代表“应用系统”。它是多用户、多任务和非常安全的系统,因此用于需要同时存储和处理敏感数据的行业。它最适合中级行业,因此用于制药行业、银行、商场、医院管理、制造业、分销…

栈队列OJ练习题(C语言版)

目录 一、括号匹配问题 思路: 完整版C语言代码: 讲解: 二、用队列实现栈 思路: 完整版C语言代码: 讲解: 三、用栈实现队列 思路: 完整版C语言代码: 讲解&#xff1a…

【C++】C++入门(下)--内联函数 auto关键字 nullptr

目录 一 内联函数 1 内联函数概念和定义 2 内联函数特性 二 auto关键字 1 auto概念 2 auto 的使用细则 (1) auto与指针和引用结合起来使用 (2) 在同一行定义多个变量 3 auto不能推导的场景 (1) auto不能作为函数的参数 (2) auto不能直接用来声明数组 4 基于范围的fo…

uniapp实现瀑布流

首先我们要先了解什么是瀑布流: 瀑布流(Waterfall Flow)是一种常见的网页布局方式,也被称为瀑布式布局或砌砖式布局。它通常用于展示图片、博客文章、商品等多个不同大小和高度的元素。 瀑布流布局的特点是每个元素按照从上到下…

椭圆曲线点加的推导公式

一、点加推导过程 1.1 背景 实数域上的椭圆曲线: y^2 =x^3+ax+b 假设P,Q,R三点的坐标分别为:P(x1,y1),Q(x2,y2),R(x3,-y3),我们这里求的是P+Q,即R的镜像点,因此R坐标为(x3,-y3)。 假设通过点P(x1,y1)点的直线方程L(x)可以表达为:y=k(x-x1)+y1 ,其中,k为直线L(x)的…

.NET CORE 3.1 集成JWT鉴权和授权2

JWT:全称是JSON Web Token是目前最流行的跨域身份验证、分布式登录、单点登录等解决方案。 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT令牌在api接口中校验用户的身份以确认用户是否有访问api的权限。 授权:这是使用JWT的…

测绘屠夫报表系统V1.0.0-beta

1. 简介 测绘屠夫报表系统,能够根据变形监测数据:水准、平面、轴力、倾斜等数据,生成对应的报表,生成报表如下图。如需进一步了解,可以加QQ:3339745885。视频教程可以在bilibili观看。 2. 软件主界面 3. …

vue3+ts+threejs 1.创建场景

效果 创建画布容器元素 <script setup lang"ts"> ... // 画布容器 const canvasRef ref<HTMLElement>() const canvasSize ref<{ width: number, height: number }>({width: 0, height: 0})// 监控更新画布尺寸 function handleResize(entry: R…

云笔记一网打尽

二、云笔记产品 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 这么多产品如何选择呢&#xff1f; 2.1、选择注重本地留存的产品 可以看到语雀出事后&#xff0c;网上的文章出场率比较高的有Obsidian和思源笔记。为什么呢&#xff1f;因为它们比较注意…

Go学习第十三章——Gin入门与路由

Go web框架——Gin入门与路由 1 Gin框架介绍1.1 基础介绍1.2 安装Gin1.3 快速使用 2 路由2.1 基本路由GET请求POST请求 2.2 路由参数2.3 路由分组基本分组带中间件的分组 2.4 重定向 1 Gin框架介绍 github链接&#xff1a;https://github.com/gin-gonic/gin 中文文档&#xf…

中颖单片机SH367309全套量产PCM,专用动力电池保护板开发资料

方案总体介绍 整套方案硬件部分共2块板子&#xff0c;包括MCU主板&#xff0c;采用SH79F6441-32作为主处理器。MCU主板包括2个版本。PCM动力电池保护板采用SH367309。 软件方案采用Keil51建立的工程&#xff0c;带蓝牙的版本&#xff0c;支持5~16S电池。 硬件方案--MCU主板 MC…

【用户登录】模块之登录认证+鉴权业务逻辑

用户登录——⭐认证功能的流程图&#xff1a; ⭐鉴权流程图&#xff1a; 用户登录功能的Java代码实现 1. 实体类-User orm框架&#xff1a;JPA Table(name "user_tab") Entity Data NoArgsConstructor AllArgsConstructor public class User implements Serializ…