概念
Qt本身并不是一种编程语言,它实质上是一个跨平台的C++开发类库,是用标准C++编写的类库,它为开发GUI应用程序和非GUI应用程序提供了各种类。
元对象系统
Qt的元对象系统提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。
组成
- QObject类是所有使用元对象系统的类的基类;
- 在一个类的private部分声明Q_OBJECT宏,使得类可以使用元对象的特性,动态属性、信号、槽;
- MOC为每个QObject的子类提供必要的代码来实现元对象系统的特性。
其他功能
QMetaObject *QObject::metaObject()
QMetaObject包含了访问元对象的一些接口函数。
const char *className() 返回类的名称字符串
QObject *newInstance()创建类的一个新的实例
QObject *obj = new QPushButton;
obj->metaObject()->className(); // returns "QPushButton"
QPushButton::staticMetaObject.className(); // returns "QPushButton"
bool QObject::inherits(const char *className)
判断一个对象实例是否是名称为className的类或QObject的子类的实例。
QTimer *timer = new QTimer; // QTimer inherits QObject
timer->inherits("QTimer"); // returns true
timer->inherits("QObject"); // returns true
timer->inherits("QAbstractButton"); // returns false
QString tr(const char *sourceText, const char *disambiguation = nullptr, int n = -1)
翻译字符串。
bool setProperty(const char *name, const QVariant &value)
设置属性。
QVariant property(const char *name) const
获取属性。
属性系统
属性定义
QT提供一个Q_PROPERTY()宏可以定义属性,它也是基于元对象系统实现的。
Q_PROPERTY(type name
( READ getFunction
[WRITE setFunction] |
MEMBER memberName [(READ getFunction
[WRITE setFunction )] )
[RESET resetFunction]
[NOTIFY notifySignal]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
- READ:指定一个读取属性值的函数,没有MEMBER关键字时必须设置READ;
- WRITE:指定一个设定属性值的函数,只读属性没有WRITE设置;
- MEMBER:指定一个成员变量与属性关联,称为可读可写的属性,无需再设置READ和WRITE;
- RESET:是可选的,用于指定一个设置属性缺省值的函数;
- NOTIFY:是可选的,用于设置一个信号,当属性值编号是发射此信号;
- DESIGNABLE:表示属性是否在Qt Designer里可见,默认是true;
- SCRIPTABLE:
- STORED:
- USER:
- CONSTANT:表示属性值是一个常数,对于一个对象实例,READ指定的函数返回值是常数,但是每个实例的返回值可以不一样,具有CONSTANT关键字的属性不能有WRITE和NOTIFY关键字;
- FINAL:所定义的属性不能被子类重载;
使用
Q_PROPERTY(bool focus READ hasFocus)
Q_PROPERTY(bool enabled READ isEnable WRITE setEnabled)
QObject::setProperty()
设置属性值
QPushButton* button = new QPushButton(this);
QObject* o = button;
o->setProperty("flat", true);
QVariant isFlat = o->property("flat");
动态属性
QObject::setProperty()函数可以在运行时为类定义一个新的属性,称之为动态属性,动态属性是针对类的实例定义的。
信号与槽
connect函数
connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method,
Qt::ConnectionType type = Qt::AutoConnection)
connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver,
const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver,
PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)
connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
示例
connect(ui->btnMax,SIGNAL(clicked()),this,SLOT(showMaximized()));
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &MainWindow::onCurrentChanged);
参数含义
- sender:发出信号的对象;
- signal:发出的信号;
- receiver:接收信号的对象;
- slot:接收到的信号之后调用的函数;
type
- Qt::AutoConnection:默认值,如果信号接收者与发射者在同一个线程,就使用这个方式,否则使用Qt::DirectConnection;
- Qt::DirectConnection:信号被发射时槽函数立即执行,槽函数与信号在同一个线程;
- Qt::QueuedConnection:在事件循环回到接收者线程后执行槽函数,槽函数与信号在不同的线程;
- Qt::BlockingQueuedConnection:与Qt::QueuedConnection类似,只是信号线程会阻塞直到槽函数执行完毕,当信号和槽函数在同一个线程时绝对不能使用这种方式,否则会造成死锁。
QObject::sender()
获取信号发射者的指针。
QTabWidget *w = qobject_cast<QTabWidget*>(sender());
//如果知道信号发送者的指针类型,直接强转
自定义信号槽
条件
- 自定义的类,要继承自QObject;
- 自定义的类,其中要声明一个宏Q_OBJECT;
- 只有满足以上两个条件才能正常使用信号槽机制。
信号
signals:
void startTimerSignal();
emit startTimerSignal();
槽
public slots:
void initChannel();
建立连接
connect(a,SIGNAL(startTimerSignal()),b,SLOT(initChannel()));
lambda表达式
connect(ui->btnSetWindowTitle,&QPushButton::clicked,this,[=](){
this->setWindowTitle("信号槽连接的5种方式");
});
匿名函数的定义
[](){
qDebug() << "lambda...";
};
匿名函数的调用
[](){
qDebug() << "lambda...";
}();
不捕获任何变量
int a= 10;
[](){
// qDebug() << a;//报错 先注释
}();
按引用捕获任何变量
[&](){
qDebug() << a++;
}();
按值捕获任何变量 a是不可变的
[=](){
qDebug() << a;//a++会报错
}();
按值捕获任何变量 + mutable
[=]() mutable{
qDebug() << a++;
}();
参数
[=](int x,int y) mutable{
qDebug() << x+y;
}(1,2);
返回值
int sum = [](int x,int y) ->int {
return x+y;
}(1,2);
int sum1 = [](int x,int y) {
return x+y;
}(1,2);
qDebug() << sum1;