Qt 元对象系统
1、QObject是所以使用元对象系统的类的基类,必须在类的开头使用Q_OBJECT宏才能使用元对象系统的特性。
2、元对象编译器MOC是一个预处理器。
3、元对象是对类的描述,包含类信息、方法、属性等元数据。
QObject类:
1、元对象(meta object):
每个QObject子类的实例都是一个元对象(静态变量staticMetaObject),函数metaObject()可以返回它的指针。
2、类型信息:QObject的inherits()函数可以判断继承关系。
3、动态翻译:函数tr()返回一个字符串的翻译版本。
4、对象树:表示对象间从属关系的树状结构。QObject提供了parent()、children()、findChildren()等函数。对象树中的某个对象被删除时,它的子对象也将被删除。
5、信号与槽:对象间的通信机制。
6、属性系统:可以使用宏Q_PROPERTY定义属性,QObject的setProperty()会设置属性的值或定义动态属性;property()函数会返回属性的值。
QMetaObejct类:
QObject* object = new QPushButton; //QObject::metaObject()返回类关联的元对象。 qDebug() << object->metaObject()->className(); //返回"QPushButton" QPushButton* pushbtn = qobject_cast<QPushButton*>(object); qDebug() << pushbtn->metaObject()->className(); //返回"QPushButton" //inherits()函数返回继承关系 qDebug() << pushbtn->inherits("QObject"); //返回 true。pushbtn是继承自QObject qDebug() << pushbtn->inherits("QTimer"); //返回 false //superClass()函数返回父类的元对象 qDebug() << object->metaObject()->superClass()->className(); //返回"QAbstractButton" object->setProperty("name", "tingtaishou"); QString name = object->property("name").toString(); const QMetaObject* meta = object->metaObject(); int index = meta->indexOfProperty("name"); QMetaProperty prop = meta->property(index); bool res = prop.isWritable();
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT Q_CLASSINFO("author","tingtaishou") Q_CLASSINFO("version","1.0.0") public: explicit Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::Widget *ui; }; #endif // WIDGET_H
#include "widget.h" #include "ui_widget.h" #include <QMetaProperty> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); this->metaObject()->classInfo(0).name(); this->metaObject()->classInfo(0).value(); this->metaObject()->classInfo(1).name(); this->metaObject()->classInfo(1).value(); } Widget::~Widget() { delete ui; }
信号与槽:
对象树:
元对象应用场景:
1、当一个窗口中有很多同类型的对象时,我们不需要将每个对象都写一个信号与槽,只需将所有对象都连接到同一个槽函数中,并在改槽函数中获取发送信号的对象(sender()函数),进而获取每个对象在创建时设置的不同的属性(ui->label_boy->setProperty("sex","boy")),从而区分不同的对象。