一.概述
Qt是对标准C++的编写的类库,引入信号与槽等概念。Qt的元对象编译器(MOC)是一个预处理器,将qt特性代码转化为标准C++形式,再由C++编译器进行编译处理。
1.元对象系统
元对象系统提供了信号与槽机制、运行时类型信息和动态属性系统等。
元对象系统有以下三个部分组成:
1. QObject
是所有使用元对象的类的基类。
2. 在每一个类的private
部分声明Q_OBJECT
宏,使得类可以使用元对象的特性。
3. MOC负责转化每一个QObject
的子类的代码实现元对象系统的特性。
信号与槽机制的简单介绍:
Signal&Slot
是Qt编程的基础,用于各个组件的通信。例如:
QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
由于connect
是静态函数,QObject
是Qt中所有类的基类,所以QObject::
可以省略。
- sender
:发射信号的对象或者组件的名称;
- receiver
:接收信号的对象或者组件的名称;
- SIGNAL
,SLOT
:Qt中的宏,用来表明信号和槽;
- signal()
:信号名称,C++中的函数;
- slot()
:槽名称,也是C++中的函数;
connect
函数具有不同的参数形式:
//形式1
QMetaObject::Connection
QObject::connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method,
Qt::ConnectionType type = Qt::AutoConnection);
//形式2
QMetaObject::Connection
QObject::connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection);
形式1就是上面例子的调用,形式2无法用于重载信号,即不同的参数的同名信号。
最后一个参数type
表示了信号与槽之间的关联方式:
默认值Qt::AutoConnection
表示:若信号的发送者和接收者在同一线程,就使用Qt::DirectConnection
,即信号被发射的同时槽函数立即执行;若不在同一线程,就使用Qt::QueuedConnection
,在事件循环回到接收者线程后执行槽函数。
在槽函数中,可以使用QObject::sender()
函数获得信号发射者的指针。
下面是一些关于信号和槽的规则:
- 一个信号可以连接多个槽;
- 多个信号也可以只连接一个槽;
- 一个信号可以连接另外一个信号;
- 信号的参数个数不能小于槽的参数个数,或者严格匹配;
- 在使用信号和槽的类,必须在private
部分声明Q_OBJECT
宏;
- 信号被发射时,与其关联的槽函数会被立即执行;另外,只有当所有关联的槽函数都被执行完毕,才会执行发射信号之后的代码。
自定义信号:声明在类中在signals:
中,无需实现,只需要发射(emit);
自定义槽:声明在slots:
中;
其它一些功能
(1). QObject::metaObject()
:返回类关联的元对象;例如:
obj->metaObject()->className(); //返回obj类名的字符串
(2). QObject::newInstance()
:返回类实例;
(3). QObject::inherits(const char *className)
:返回一个对象实例是否为className
类或者子类。
(4). QObject::tr(),QObject::trUtf8()
:国际化,用来翻译字符串。
(5). QObject::setProperty(),QObject::property()
:用于通过属性名称动态设置和获取属性值。
(6). qobject_cast
:动态投射,用法与dynamic_cast
基本一致。
属性系统
Q_PROPERTY()
:定义属性,格式如下:
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifyFunction]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
[]
表示里面的属性时可选的,Q_PROPERTY
定义的是一个返回值为type
,名称为name
的属性,用READ,WRITE
关键字定义了该属性的读取、写入函数。
MEMBER
:指定一个成员变量与属性关联,称为可读可写的属性,无需再设置READ
,WRITE
。例如:
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
Q_PROPERTY(int score MEMBER m_score)
第一句定义的是一个返回值为int
,名称为age
即’年龄’的属性,用READ,WRITE
关键字定义了该属性的读取、写入函数age()
、setAge()
以及改变函数ageChanged()
。
第二句定义的是一个返回值为int
,名称为score
即’分数’的属性,并且利用MEMBER
指定一个成员变量m_score
与该属性关联。
类的一些附加信息: 使用Q_CLASSINFO
Q_CLASSINFO("author", "xxx")
Q_CLASSINFO("company", "xxx")
Q_CLASSINFO("version", "1.0.0")
2. Qt全局定义
头文件<QtGlobal>
包含了一些Qt的全局定义,包括基本数据、函数和宏。
(1).基本数据
常见的例如:
qint8 : signed char 1个字节
qint16 : signed short 2个字节
qint32 : signed int 4个字节
qint64/qlonglong : long long int 8个字节
quint8/uchar :unsigned char 1个字节
quint16/ushort :unsigned short 2个字节
quint32/uint : unsigned int 4个字节
ulong :unsigned long 8个字节
quint64/qulonglong : unsigned long long int 8个字节
qreal : double 8个字节
qfloat16 : 2个字节 <QFloat16>头文件
(2).函数
常见的一些全局模板函数:
T qAbs(const T &value)
double qInf()
bool qIsFinite(double d)
bool qIsInf(double d)
bool qIsNaN(double d)
const T &qMax(const T &value1, const T &value2)
const T &qMin(const T &value1, const T &value2)
qint64 qRound64(double value)
int qRound(double value)
int qrand()
bool qFuzzyCompare(double p1, double p2)
bool qFuzzyIsNull(double d)
从函数的名称都可知其含义,另外还有一些基本数学运算再头文件<QtMath>
中。
(3).宏
QT_VERSION
:版本号,数值形式为0xMMNNPP
。例如:
编译器为Qt5.9.2,那么QT_VERSION
即为:0x050901
。
QT_VERSION_CHECK
,使用方法如下:
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
...
#endif
QT_VERSION_STR
:返回版本号的字符串,例如5.9.2
。
QT_BYTE_ORDER,Q_BIG_ENDIAN,Q_LITTLE_ENDIAN
:系统内存的字节序,大端模式,小端模式。例如:
#if (QT_BYTE_ORDER == QT_BIG_ENDIAN)
...
#endif
Q_UNUSED(name)
:忽略没有使用的参数的编译警告。
就不一一介绍了。
容器类
QT中的容器类和STL中的容器类是类似的,但是更加轻巧,线程安全的,易用。
(1). 顺序容器:QVector, QStack,QQueue,QList,QLinkedList
(2). 关联容器:QMap,QMultiMap,QHash,QSet
(3). 相关的迭代器, 参考STL的用法。
(4). foreach
关键字,头文件<QtGlobal>
,用法
:
foreach(variable, container)
注意,利用foreach
遍历容器是创建容器的副本,所以是只读不写。
Qt的相关模块。
未完待续。