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('')
print(obj0.findChild(QObject,''))
这样,是可以查找到对应的子对象的,然而可以要求只查询直系的子对象
print(obj0.findChild(QObject,'',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('')
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('') 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('')
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()
其实上面的内容就是最开始的几点比较重要,后面的做大概的了解就可以了。
GUI学习之三——QObject学习总结的更多相关文章
- AspectJ基础学习之三HelloWorld(转载)
AspectJ基础学习之三HelloWorld(转载) 一.创建项目 我们将project命名为:aspectjDemo.然后我们新建2个package:com.aspectj.demo.aspect ...
- Linux学习之三-Linux系统的一些重要配置文件
Linux学习之三-Linux系统的一些重要配置文件 1.网卡配置文件 /etc/sysconfig/network-scripts/ifcfg-eth0 说明: DEVICE=eth0 ...
- C++11并发学习之三:线程同步(转载)
C++11并发学习之三:线程同步 1.<mutex> 头文件介绍 Mutex又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mutex> 头文 ...
- jackson学习之三:常用API操作
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- [WebView学习之三]:使用WebView来创建Apps
上一篇我们学习了([WebView学习之二]:使用Web Apps 支持不同分辨率屏),今天我们来继续学习. (博客地址:http://blog.csdn.net/developer_jiangqq) ...
- 强化学习之三点五:上下文赌博机(Contextual Bandits)
本文是对Arthur Juliani在Medium平台发布的强化学习系列教程的个人中文翻译,该翻译是基于个人分享知识的目的进行的,欢迎交流!(This article is my personal t ...
- python3.4学习笔记(七) 学习网站博客推荐
python3.4学习笔记(七) 学习网站博客推荐 深入 Python 3http://sebug.net/paper/books/dive-into-python3/<深入 Python 3& ...
- 基于pyqt5和openpyxl和Pyinstaller的青年大学习检查未学习人数的脚本
前几天接到团支书的一个需求,因为学校给的名单是青年大学习已学习的名单,然而要知道未学习的名单只能从所有团员中再排查一次,过程相当麻烦.团支书跟我抱怨后,刚好我也学过一些操作办公软件的基础.打包pyth ...
- (转)Predictive learning vs. representation learning 预测学习 与 表示学习
Predictive learning vs. representation learning 预测学习 与 表示学习 When you take a machine learning class, ...
随机推荐
- java8-函数编程
在Function里面看到一个很奇怪的代码 static <T> Function<T, T> identity() { return t -> t; } 手动写了几个代 ...
- Logparser介绍
原文链接:https://www.cnblogs.com/Jerseyblog/p/3986591.html Logparser是一款非常强大的日志分析软件,可以帮助你详细的分析网站日志.是所有数据分 ...
- python3 里安装cv2
电脑上同时有python2 和python3,python2 里有cv2,Python3里没有. 用pip3 install opencv-python 安装,提示: You are using pi ...
- python学习笔记---环境的安装,pip命令,数据类型,运算
1.进入python环境: python 2:py -2 python 3:py -3 2.退出python环境 exit()/quit()/ctrl+z+enter ctrl+z+enter没有尝试 ...
- Java面试题 BAT 大公司面试题整理总结!
本文只列出了问题,答案还是需要需要自己的总结,很多时候自己总结出来的语言在面试时比硬背的效果好很多. 这些题目是网友去百度.小米.乐视.美团.58.猎豹.360.新浪.搜狐等一线互联网公司面试被问到的 ...
- Windows 2008 R2 域控制器防止意外删除现有OU的设置
Windows 2008 R2 域控制器防止意外删除现有OU(组织单元)的设置:1.以管理员身份运行Active Directory的Windows PowerShell模块: 2.键入以下命令来检查 ...
- ESLint具体规则设置
"no-alert": 0,//禁止使用alert confirm prompt "no-array-constructor": 2,//禁止使用数组构造器 & ...
- NamedParameterJdbcTemplate
NamedParameterJdbcTemplate 在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制. 定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参 ...
- [PHP] 常备的现代 PHP 项目开发准备
[ Windows 开发环境 ] phpStudy(http://phpstudy.php.cn/) 现在一般选择版本: php7.1 + nginx,常用 curl.openssl 扩展选择打开. ...
- LVS负载均衡
1.LVS负载均衡 实现LVS负载均衡转发方式有三种,分别为NAT.DR.TUN模式,LVS均衡算法包括:RR(round-robin).LC(least_connection).W(weight)R ...