GUI学习之三——QObject学习总结

鉴于PyQt控件的继承关系,我们先学习PyQt控件的基类——QObject。

 一.所有的QT对象的基类

我们先看一下PyQt里空间的继承关系,稍微改一下代码,显示出继承关系

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
class Window(QWidget):
    def test(self):
        mros = QObject.mro()
        for mro in mros:
            print(mro)

window = Window()
window.test()
sys.exit(app.exec_())
<class ‘PyQt5.QtCore.QObject‘>
<class ‘sip.wrapper‘>
<class ‘sip.simplewrapper‘>
<class ‘object‘>

这就表明了QWidget这个控件的继承呢个关系,可以看出来所有的类,都是基于Python的object这个类的

二.QObject的功能作用

由于所有的控件都是继承了QObject,所以他所有的API是各种控件都具备的,下面列举的就是他的功能作用

1.对戏那个名称、属性的操作(API):

window = QWidget()
window.setObjectName()          #给对象设定一个名称(一般这个名称在整个项目里是唯一的)
window.objectName()             #获取这个对象的名称
window.setProperty()            #给对象设置一个属性
window.property()               #获取对象的某个属性
window.dynamicPropertyNames()   #获取一个对象中通过setProperty设置的属性名名称

这里前几个很好理解,设置属性的我们来看一下怎么用

window = QWidget()
label = QLabel(window)
label.setProperty(‘stat‘,‘on‘)
label.setProperty(‘color‘,‘green‘)
print(label.property(‘stat‘))
print(label.dynamicPropertyNames())

on
[PyQt5.QtCore.QByteArray(b‘stat‘), PyQt5.QtCore.QByteArray(b‘color‘)]

运行结论

特别是在结合qss的ID选择器,属性选择器统一设定样式,具体用法我们在后期再说明。

2.父子对象操作

先看下父子对象操作的API

window.setParent()      #设置父对象
window.children()       #获取所有子对象
window.findChild()      #查询某一个子对象
window.findChildren()   #查询多个子对象

然后我们要构造这样的父子关系图,该怎么做呢?

obj0 = QObject()
obj1 = QObject()
obj2 = QObject()
obj3 = QObject()
obj4 = QObject()
obj5 = QObject()

obj1.setParent(obj0)
obj2.setParent(obj0)
obj3.setParent(obj1)
obj4.setParent(obj2)
obj5.setParent(obj2)

就是这么个结构,将这个的目的是什么呢?

我们可以搞清这些东西:

a.一个对象只能有一个父对象,这个父对象是最后被设置的。

obj2.setParent(obj0)
obj2.setParent(obj1)

那么obj2的父对象就是obj1.

b.用childern获取子对象只能获得直系的子对象

print(obj0.children())

[<PyQt5.QtCore.QObject object at 0x000001E2F4724828>, <PyQt5.QtCore.QObject object at 0x000001E2F4724798>]

运行结论

[<PyQt5.QtCore.QObject object at 0x000001E2F4724828>, <PyQt5.QtCore.QObject object at 0x000001E2F4724798>]分别是OBj1和OBJ2的地址

c.findChild常规情况时递归的查找要求的子对象,比如我们把obj3的名字设定为3

obj3.setObjectName(‘3‘)
print(obj0.findChild(QObject,‘3‘))

这样,是可以查找到对应的子对象的,然而可以要求只查询直系的子对象

print(obj0.findChild(QObject,‘3‘,Qt.FindDirectChildrenOnly))

这样查询结果就是None了。

d.如果用findChildren常规情况则返回所有的子对象(包括子对象的子对象)

print(obj0.findChildren(QObject))

利用上述的方式,可以批量对控件熟属性进行设置

window = QWidget()
label_1 = QLabel(window)
label_1.move(100,100)
label_1.setText(‘标签1‘)
label_2 = QLabel(window)
label_2.setText(‘标签2‘)
label_2.move(200,100)
btn = QPushButton(window)
btn.move(200,200)
window.show()
for sub_widget in window.findChildren(QLabel):   #遍历对话框内的Label控件,并将其背景色设置为红色
    sub_widget.setStyleSheet(‘background-color:red‘)

e.如果父对象被释放,则子对象被自动释放:用在平时的场景中,就是一个对话框里,包含了很多的控件,这些控件都是这个对话框的子控件。这些子控件收父控件的区域所控制,如果父控件被删除(关闭)时,子控件也相应被删除。

也就是说,在一个GUI里的内存管理机制是QObject的继承树——所有的对象都是直接或间接的继承自QObject,当创建一个对象时,如果使用了其他的对象作为其父对象,那么他就会被追加到父对象的children列表里。当父对象被销毁是,这个QObject也会被销毁。

3.信号——槽机制

信号(signal)和槽(slot)是Qt中的核心机制,主要作用在于对戏那个之间进行通讯,所有继承自QWidget的控件都支持信号——槽的机制

信号——当一个空间的状态发生改变时,想外界发出的信息

槽——一个执行某些操作的函数或方法

这个机制具有以下几个特点

  a.一个信号可以连接多个槽函数

  b.一个信号也可以连接另外一个信号

  c.信号的参数可以是任何Python的数据类型

  d.一个槽可以监听多个信号

信号处理的常用API有下面几种

object.信号.connert(槽)   #连接信号和槽
object.disconnect()       #断开信号和所有槽的连接
object.blockSignals(bool) #临时取消指定的信号和所有槽的连接bool为True时阻塞,False时取消阻塞
obj.signalsBlocked()      #获取信号是否被阻塞,若阻塞返回值为True
obj.receivers(信号)       #返回信号连接的槽个数

下面就是一个信号与槽的案例,点击按钮,每次点击,标签显示加上‘点击’两个字

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.resize(500,500)
btn = QPushButton(window)
label = QLabel(window)
btn.move(100,200)
btn.resize(100,50)
btn.setText(‘点击‘)
label.resize(10,50)
label.move(50,100)
def test():
    data = label.text()
    data += ‘点击‘
    label.setText(data)
    label.adjustSize() #控件自适应大小,下一章会讲
btn.clicked.connect(test)
window.show()

sys.exit(app.exec_())

信号——槽案例

进阶案例——改变title后将改变的值付给title

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle(‘123‘)
def test(title):
    print(title)
    window.windowTitleChanged.disconnect()  #断开连接
    data = title
    data+= ‘更改后‘
    window.setWindowTitle(data)
    window.windowTitleChanged.connect(test) #重新连接

window.show()
# btn.clicked.connect(test)
# window.windowTitleChanged.connect(test)
window.windowTitleChanged.connect(test)
window.setWindowTitle(‘456‘)

sys.exit(app.exec_())

信号——槽进阶案例

在这个案例中槽里将信号和槽做了一次断开,执行完后重新连接,因为信号是改变title后调用槽函数,槽函数是将新的字符串赋值给title。在这里如果不将信号和槽断开后会进入一个死循环。必须要分开后重新连接。

4.类型判定

先看一下API

obj.inherits(父类)     #返回对象是否属于父类
obj.isWidgetType()    #返回对象是否属于QWidget

案例——判定控件是否为标签,将所有标签背景色设为red

from PyQt5.Qt import *
import sys
app=QApplication(sys.argv)
window = QWidget()
a = QLabel(window)
a.move(100,200)
b = QPushButton(window)
b.move(300,200)
c = QLabel(window)
c.move(200,200)
for widget in window.children():
    if widget.inherits("QLabel"):
        widget.setStyleSheet(‘background-color:red‘)
window.show()

sys.exit(app.exec_())

类型判定案例

 5.对象删除

API

obj.deleteLater()

删除一个对象是,也会解除它与父对象之间的关系,deleteLater()并没有将对象立即销毁,而是想主消息循环发送一个事件,在下个消息循环时才销毁对象,这样做的好处就是可以在这些演示产出的时间内完成一些操作,坏处局势内存释放会比较不及时。

6.事件机制

这是个比较复杂的过程,后期再详细讲述。

7.定时器

API:

obj.startTimer(1000,Qt.PreciseTimer)   #精准定时器,ms级
obj.startTimer(1000,Qt.CoarseTimer)    #粗定时器,5%准确度
obj.startTimer(1000,Qt.VeryCoarseTimer)#最粗的定时器,s级
obj.kellTimer(timer_ID)                #停止定时
timeEvent()                            #定时器执行事件,在Object内,需要重构

每次启动一个timer时都会生成一个timer_ID ,这个ID是唯一的,停止定时时需要用到这个ID。我们看一下最简单的定时器

from PyQt5.Qt import *
import sys
class MyLabel(QLabel):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)          #重新对控件进行封装
        self.setText(‘10‘)
        self.setStyleSheet(‘font-size:22px;‘)
        self.resize(300,200)
        self.timer_id = self.startTimer(1000)     #在这里生成timer_id
    def timerEvent(self, a0: ‘QTimerEvent‘):
        current_sec = int(self.text())
        current_sec -= 1
        self.setText(str(current_sec))
        if current_sec == 0:
            self.setText("stop!")
            self.killTimer(self.timer_id)
app=QApplication(sys.argv)
window = QWidget()
window.resize(800,800)
label = MyLabel(window)   #这里实例化的重构后的QObject
label.move(200,200)
window.show()
sys.exit(app.exec_())

定时器案例一

这里由于对Label进行的高度的封装,导致这个控件不够灵活,具体的实现方法我们在后期的自定义控件里可以再聊!

最后,QObject还有自身的两个信号,有的在上面已经讲过了

obj.objectNameChanged()
destroyed()

其实上面的内容就是最开始的几点比较重要,后面的做大概的了解就可以了。

原文地址:https://www.cnblogs.com/yinsedeyinse/p/10662434.html

时间: 2024-10-19 02:56:23

GUI学习之三——QObject学习总结的相关文章

cc2530 makefile简略分析 &lt;contiki学习之三&gt;

前面将contiki的makefile框架都理了下,这篇就以cc2530为收篇吧,也即makefile分析就该到此为止了. contiki/examples/cc2530dk 打开Makefile如下图: 第一行的 "CONTIKI_PROJECT"变量依赖于该目录下的  blink-hello.c  hello-world.c  sensors-demo.c  timer-test.c 4个C源文件 第五行的"CONTIKI"变量被定义成 contiki/ 路径,

【转】MYSQL入门学习之三:全文本搜索

转载地址:http://www.2cto.com/database/201212/173873.html 一.理解全文本搜索 www.2cto.com 1.MyISAM支持全文本搜索,而InnoDB不支持. 2.在使用全文本搜索时,MySQL不需要分别查看每个行,不需要分别分析和处理每个词.MySQL创建指定列中各词的一个索引,搜索可以针对这些词进行.这样MySQL可以快速有效地决定哪些词匹配,哪些词不匹配,它们匹配的频率,等等. 二.使用全文本搜索 1.为了进行全文本搜索,必须索引被搜索的列,

mysql学习之三:sql语句学习

SQL 是一门 ANSI 的标准计算机语言,用来访问和操作数据库系统.SQL 语句用于取回和更新数据库中的数据.SQL 可与数据库程序协同工作,比如MySQL. MS Access.DB2.Informix.MS SQL Server.Oracle.Sybase 以及其他数据库系统. 不幸地是,存在着很多不同版本的 SQL 语言,但是为了与 ANSI 标准相兼容,它们必须以相似的方式共同地来支持一些主要的关键词(比如 SELECT.UPDATE.DELETE.INSERT.WHERE 等等).

AspectJ基础学习之三HelloWorld(转载)

AspectJ基础学习之三HelloWorld(转载) 一.创建项目 我们将project命名为:aspectjDemo.然后我们新建2个package:com.aspectj.demo.aspect 和 com.aspectj.demo.test 前者用来方apsect.后者用来放测试类.如果你仔细的话,你会发现Aspectj的项目上面有个AJ的标志. 二.创建Aspect 首先我们创建HelloWorld.java.他包含main()方法,但是没有方法体,代码如下: [java] view

PGM学习之三 朴素贝叶斯分类器(Naive Bayes Classifier)

介绍朴素贝叶斯分类器的文章已经很多了.本文的目的是通过基本概念和微小实例的复述,巩固对于朴素贝叶斯分类器的理解. 一 朴素贝叶斯分类器基础回顾 朴素贝叶斯分类器基于贝叶斯定义,特别适用于输入数据维数较高的情况.虽然朴素贝叶斯分类器很简单,但是它确经常比一些复杂的方法表现还好. 为了简单阐述贝叶斯分类的基本原理,我们使用上图所示的例子来说明.作为先验,我们知道一个球要么是红球要么是绿球.我们的任务是当有新的输入(New Cases)时,我们给出新输入的物体的类别(红或者绿).这是贝叶斯分类器的典型

Spring MVC学习之三:处理方法返回值的可选类型

转自:http://www.cnblogs.com/cuizhf/p/3810652.html ———————————————————————————————————————————————————————————— spring mvc处理方法支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, String, void.下面将对具体的一一进行说明: ModelAndView @RequestMapping("/show1") publ

【SQL Server】系统学习之三:逻辑查询处理阶段-六段式

一.From阶段 针对连接说明: 1.笛卡尔积 2.on筛选器 插播:unknown=not unknuwn 缺失的值: 筛选器(on where having)把unknown当做FALSE处理,排除在筛选结果之外.如果比较两个null,结果是不相等的,false check约束中当做true,例如要求某列大于0,当插入null时是成功的,认为null>0是ture.如果比较两个null,结果是相等的,这种比较在unique约束.集合运算(例如union .except).排序.分组,都认为是

SSH学习之三 SSH与SCP无密码登录

通常情况下,每次使用ssh登录或使用scp复制远程系统的文件时,都需要提供密码,然后才能做进一步的处理.为了省略输入密码这一步骤,有时可以采用Shell脚本的方法解决,但这需要把手工输入的密码以明码形式放在脚本文件中. 利用密钥配置文件,OpenSSH可以是ssh远程登录与scp文件复制的操作过程中省略密码验证的中间环节.为此,ssh客户端首先应建立OpenSSH连接,然后自动地想服务器发送其公钥.之后,服务器即可根据相应用户主目录中预定义的密钥列表,对收到的密钥进行比较.如果存在匹配的密钥,服

OpenStack 入门学习之三:单节点icehouse网桥的配置

部署完icehouse,安装完实例之后,如果虚拟主机需要和外部进行通信,还需要对宿主机的网桥进行配置 具体配置如下 修改ifcfg-em1的内容为以下内容: DEVICE=em1 ONBOOT=yes DEVICETYPE=ovs TYPE=OVSPort OVS_BRIDGE=br-ex #HWADDR=F8:B1:56:AE:3A:84 #TYPE=Ethernet #UUID=6f49b547-f1f8-4b21-a0fc-68791a5237dd #BOOTPROTO=static #I