概念

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;
02-21 18:17