什么是元对象机制 元对象机制不是Qt独创的术语,而是一个编程语言领域的通用概念。 元对象机制(Meta Object Facility)最早起源于建模语言UML,是一套用来定义和描述对象结构和行为的机制。 元数据(Metadata)即用来描述其它数据特征和属性的数据 Qt的元对象机制,同样也是为了实现这样的功能,Qt框架通过生成一个QMetaObject类来记录类名,类继承关系,定义常用的Qt类操作,执行槽函数
怎么使用元对象机制 大家只要使用过Qt进行过编程,一定就使用过Qt元对象机制。 只不过Qt框架为我们屏蔽了细节,通过Moc编译器自动帮我们实现了这些代码,我们直接调用封装好的API就可以使用这些功能。 比如我们已经使用过的signal关键字,slot关键字,connect函数,还有后面我们会提到的类型识别,文字国际化,QProperty,QVariant等,几乎所有Qt的核心功能,都离不开元对象机制,他是Qt对象的核心 使用方法也很简单,大家应该都已经使用过,继承QObject,在类的头文件中声明Q_OBJECT宏即可 记住,Q_OBJECT宏一定要声明在头文件中,而不是cpp文件中,否则在其它文件中将无法使用元对象功能
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
什么是Moc编译器 Qt是基于标准的C++语言实现的,但是我们可以看到,emit,signal,slot等关键字,都不是C++语言本来就有的,而是Qt框架自己实现的 Qt代码是无法作为普通的C++项目直接打开运行的,它必须经过Qt自己的编译器翻译成标准的C++代码才能运行 这个编译器就叫做Moc编译器,它是Meta Object Compiler的缩写,即原对象编译器 比如我们定义了一个名为mainwindow的QObject类,在编译目录下,我们可以看到,Qt帮我们生成了一个名为moc_mainwindow.cpp的文件,这就是Moc编译器编译出来的标准C++文件,文件中的大多函数都和QMetaObject挂钩,这就是Qt元对象
static const uint qt_meta_data_MainWindow[] = {};
void MainWindow::qt_static_metacall(}
QT_INIT_METAOBJECT const QMetaObject MainWindow::staticMetaObject = {};
const QMetaObject *MainWindow::metaObject() const {}
void *MainWindow::qt_metacast(const char *_clname) {}
int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) {}
QMetaObject提供了哪些功能
- 定义元对象
static const QMetaObject staticMetaObject;
- 获取元对象
virtual const QMetaObject *metaObject() const;
- 动态类型转换
virtual void *qt_metacast(const char *);
- 槽函数调用
virtual int qt_metacall(QMetaObject::Call, int, void **);
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
- 动态执行元方法,槽函数和Invokable函数都能被动态执行
static bool QMetaObject::invokeMethod(
QObject *obj, const char *member,
Qt::ConnectionType type,
QGenericReturnArgument ret,
QGenericArgument arg1,
QGenericArgument arg2,
...
QGenericArgument arg9
)
//调用槽函数compute(QString, int, double),返回QString
QString retval;
QMetaObject::invokeMethod(
obj, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, retval),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7)
);
//调用QThread槽函数quit()
QThread thread;
QMetaObject::invokeMethod(thread, "quit", Qt::QueuedConnection);
- 动态设置字段属性
//通过Q_PROPERTY宏声明一个可自定义属性的字段
Q_PROPERTY(
type name
MEMBER memberName
READ getFunction
WRITE setFunction
RESET resetFunction
NOTIFY notifySignal
)
//普通的类字段
private:
int mValue;
//通过Q_PROPERTY宏,赋予字段动态设置属性的功能
Q_PROPERTY(int value MEMBER mValue NOTIFY valueChanged);
//动态设置和获取属性
obj.setProperty("value", 15);
obj.property("value").toString();
- 字符串国际化
static QString QObject::tr(const char *, const char *, int)
static QString QObject::trUtf8(const char *, const char *, int)