PySide6.QtCore
Pyside6.QtCore是PySide6的核心库,提供了以下的功能:
- 提供了信号槽机制用于对象之间的无缝沟通
- 可查询和可设计的对象属性
- 可继承和可查询的对象树
使用元对象系统保证了信号槽机制的实现。
The Meta-Object System
元对象系统与自省机制
元对象系统提供了信号槽机制用于内部对象的交流/运行时的类型信息/动态的属性系统。
元对象系统基于以下三点:
- QObject是所有对象能够使用元对象系统的类的基类。
- 在类的私有部分使用宏Q_OBJECT表示允许使用元对象系统,比如动态属性,信号槽等
- 元对象编译器(moc)支持所有QObject的子类使用代码实现元对象特性。
moc在读取C++文件的时候,如果发现了包含Q_OBJECT的类,则会为每一个类创建另一份包含元对象代码的C++文件。要么是在文件中添加代码,要么是将编译完的文件链接到类的实现中。
除了信号槽以外,还提供了其他的一些特性。
- metaObject() 返回与本类相关的元对象
- className() 在运行时返回类名,而不依赖运行时类型信息机制
- inherits() 返回一个对象是否是继承自QObject继承树中的一个特定对象
- tr() 国际化字符串转换
- setProperty() property() 通过名称动态设置和获取属性
- QMetaObject::newInstance() 创建一个新的实例
在C++中需要注意,继承QObject之后需要显示使用宏Q_OBJECT,但是PySide6中可以不使用宏Q_OBJECT,仅仅继承QObject即可。
Object Model
标准的c++提供了高效的运行时支持,但是其静态特性在某些特定的领域不够灵活。而图形化用户界面编程是一个对运行效率和高水准灵活性要求都比较高的领域。Qt的Object Model在保证C++速度的前提下,兼顾了灵活性。
Qt在C++的基础上增加了部分特性:
- 一个有效的对象交流机制;signals-slots
- 可查询和可设计的对象属性
- 强大的事件和事件过滤器
- 丰富的语言国际化设计
- 复杂的间隔驱动计时器,可以在事件驱动的GUI中优雅地集成许多任务
- 可继承和可查询的对象树,能够以以一种自然的方式来组织对象间的关系
- 守护指针,当指针指向的对象被销毁的时候,指针自动置0。
- a dynamic cast that works across library boundaries. (没看太懂。。)
- 支持自定义创建
将Qt Object当作一个个体而不是数值来处理,前者有独立的身份,通过clone方法复制,复制得到的是一个新的个体。后者只有一个数值通过copy或者赋值创建,指向同一个个体。所以Qt Qobject有以下的一些特点:
- 有独立的名称QObject::objectName()
- 在对象继承中有自己独立的位置,复制的时候如何确定复制体的位置
- 能够连接到其他的Qt Object中或者接收信号,在复制的时候我们要注意这种连接关系要如何处理
- 在运行时能够添加新的属性,这个在复制的时候如何处理。
Qt 命名空间包含整个 Qt 库中使用的其他标识符
Object Trees & Ownership
QObject以对象树的形式来组织对象之间的关系。当你创建一个对象B继承了A,那么对象B就添加到A的children()列表中,并且在A删除的时候B也会同时删除。
QQuickItem有visual parent这样一个概念,这点与QObject parent是有所区别的。可以参考Concepts - Visual Parent in Qt Quick
Signals and Slot
信号和槽用于对象之间的通信。是Qt的一个核心功能,也是与其他框架最大的差别。
- 信号(Signal):当特定事件发生的时候会发出信号。
- 槽(Slot):为了响应特定信号而调用的函数。但是同时也是一个普通的函数
所有继承自QObject及其子类的类都可以包含信号和槽。当对象变更状态的时候,会发出对应的信号。 信号和槽可以以任意数量连接,信号也可以和信号连接。所有继承自QObject及其子类的类都可以包含信号和槽。当对象变更状态的时候,会发出对应的信号。
信号和槽的特性:
- 类型安全:信号和槽签名必须匹配(即参数个数即类型必须匹配)。并且可以接受任意数量和类型的参数。
- 松耦合:发出信号的类及不关心也不知道哪些槽接受信号。当信号和槽连接上之后,将会在正确的时间被调用。
信号是公共访问的函数,可以从任何位置发出,但最好只在本类及其子类中发出(为了降低代码的耦合度)。一旦信号发出,那么信号对应的槽函数会按顺序立即执行,并在返回之后执行后面的代码。 信号通过emit进行发出。 具体实现及调用方式
- signal = Signal(p1[option])
- obj.signal.emit(p1[option])
槽是一个普通的函数,但是可以连接到信号上。 唯一特殊的是可以连接到信号上。 槽的连接:
- obj.signal.connect(slot_func)