Qt元对象系统:QMetaObject

一、描述

此类包含有关Qt对象的元信息。Qt为应用程序中使用的每个 QObject 子类创建一个 QMetaObject 实例,该实例存储 QObject 子类的所有元信息。

二、静态成员函数

1、QByteArray normalizedSignature(const char *method)

规范化给定方法的签名。Qt使用规范化签名来决定给定的信号和槽是否兼容。

规范化:

  • 将空格减少到最小
  • 将 const 移到最前面适当的位置,
  • 用值替换 const 引用。
signals:
    void userNameChanged(const QString & userName);
    void passwordChanged(const QString password);

    qDebug()<<this->staticMetaObject.normalizedSignature(SIGNAL(userNameChanged(const QString     &     userName)));
    qDebug()<<this->staticMetaObject.normalizedSignature(SIGNAL(passwordChanged(const     QString     password)));

 

2、QByteArray normalizedType(const char *type)

规范化类型。

QByteArray normType = QMetaObject::normalizedType(" int    const  *");
// normType == "const int*"

3、bool checkConnectArgs(const char *signal, const char *method)

信号和方法参数是否兼容。信号和方法均应规范化。

    static const QMetaObject meteObject = this->staticMetaObject;
    qDebug()<<meteObject.checkConnectArgs(meteObject.normalizedSignature(SIGNAL(userNameChanged(const QString & userName))),
                                          meteObject.normalizedSignature(SLOT(onUserChanged(const QString & userName))));

    qDebug()<<meteObject.checkConnectArgs(SIGNAL(userNameChanged(const QString & userName)),
                                          SLOT(onUserChanged(const QString & userName)));

      bool checkConnectArgs(const QMetaMethod &signal, const QMetaMethod &method)

signals:
    void userNameChanged(const QString & userName);

private slots:
    void onUserChanged(const QString &userName);

    auto meteObject = this->staticMetaObject;
    auto signalIndex = meteObject.indexOfSignal("userNameChanged(QString)");
    QMetaMethod signal = meteObject.method(signalIndex);

    auto funIndex = meteObject.indexOfMethod("onUserChanged(QString)");
    QMetaMethod fun = meteObject.method(funIndex);
    qDebug()<<meteObject.checkConnectArgs(signal,fun);//true

4、void connectSlotsByName(QObject *object)

递归搜索给定对象及其所有子对象,并将来自这些子对象的匹配信号连接到以下形式的槽:

void on_<object name>_<signal name>(<signal parameters>);

假设一个类型为 QPushButton 的对象,对象名为 button1,捕捉按钮 clicked() 信号的槽为:void on_button1_clicked();

5、bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), ......)

调用对象obj上的成员 member(信号或槽)。如果可以调用该成员,则返回 true。如果没有此成员或参数不匹配,则返回false。

调用可以是同步的,也可以是异步的,具体取决于 type:

  • Qt::DirectConnection:立即调用该成员。
  • Qt::QueuedConnection:应用程序进入主事件循环后发送 QEvent 并调用该成员。
  • Qt::BlockingQueuedConnection:将以与 Qt::QueuedConnection 相同的方式调用该成员,但当前线程将阻塞。使用此连接类型与在同一线程中的对象之间通信将导致死锁。
  • Qt::AutoConnection:如果 obj 与调用者位于同一线程中,则同步调用该成员,否则将异步调用该成员。

调用的返回值放在 ret 中。如果调用是异步的,则无法计算返回值。

最多可以向成员函数传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8、val9)。

QGenericArgument QGenericReturnArgument 是内部帮助程序类。因为可以动态调用信号和槽,所以必须使用 Q_ARG() 和 Q_RETURN_ARG() 宏将参数括起来。Q_ARG() 接受类型名称和该类型的常量引用Q_RETURN_ARG() 接受类型名和非常量引用

只需要将信号或槽的名称传递给此函数,而不需要传递整个签名(只传递名称不用包含参数)。

例如,在 QThread 上异步调用 quit() 槽:

QMetaObject::invokeMethod(thread, "quit",Qt::QueuedConnection);

对于异步方法调用,参数必须是Qt的元对象系统已知的类型,因为Qt需要复制参数以在幕后事件中存储它们。对于自定义类型,在调用之前需要使用 qRegisterMetaType() 注册数据类型。

示例:同步调用某个任意对象 obj 上的 compute(QString, int, double) 槽:

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));

这里如果 “compute” 槽没有按指定顺序精确地接受一个QString、一个int、一个double,则调用将失败。

      bool invokeMethod(QObject *obj, const char *member, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(0), ......)

此重载始终使用连接类型 Qt::AutoConnection 调用成员。

      bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericArgument val0 = QGenericArgument(0), ......)

如果成员函数无返回值,则可以使用此重载。

      bool invokeMethod(QObject *obj, const char *member, QGenericArgument val0 = QGenericArgument(0), ......)

此重载使用连接类型 Qt::AutoConnection 调用成员函数,并忽略返回值。

      template <typename Functor, typename FunctorReturnType> bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)

在 context 的事件循环中调用 function 。function 可以是函子或指向成员函数的指针。

如果可以调用函数,则返回 true。如果没有此类函数或参数不匹配,则返回 false。

函数调用的返回值放在 ret 中。

class test
{
public:
    test() = default;
    void operator()()
    {
        qDebug()<<"run test()";
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.show();
    QMetaObject::invokeMethod(&a,test());

    return a.exec();
}

      template <typename Functor, typename FunctorReturnType> bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret)

使用连接类型 Qt::AutoConnection 在 context 的事件循环中调用 function。function 可以是函子或指向成员函数的指针。

如果可以调用函数,则返回 true。如果没有此类成员或参数不匹配,则返回 false。

函数调用的返回值放在 ret 中。

三、非静态成员函数

1、QMetaClassInfo classInfo(int index)

返回具有给定索引的类信息项的元数据。

class Widget : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("作者", "张三")
    Q_CLASSINFO("时间", "2020-1-1")

......
};

    QMetaClassInfo info = this->staticMetaObject.classInfo(0);
    qDebug()<<info.name()<<info.value()<<(info.enclosingMetaObject() == this->metaObject());//作者 张三 true

2、int classInfoCount()

返回此类中类信息的项数。

3、int classInfoOffset()

返回此类的类信息偏移量,即该类第一个类信息项的索引位置。

如果类没有包含类信息的超类,则偏移量为0;否则,偏移量是类超类中所有类信息项的总和。

class Widget : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("作者", "张三")
    Q_CLASSINFO("时间", "2020-1-1")

........
};

class Widget_child : public Widget
{
    Q_OBJECT
    Q_CLASSINFO("此类作者", "李四")

public:
    Widget_child(QWidget *parent = nullptr);
};

Widget_child::Widget_child(QWidget *parent)
    :Widget(parent)
{
    qDebug()<<this->staticMetaObject.classInfoOffset();//2
}

4、const char * className()

返回类名。

5、int indexOfClassInfo(const char *name)

查找类信息项名称并返回其索引,没有这个名词的类信息项则返回-1。

class Widget : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("作者", "张三")
    Q_CLASSINFO("时间", "2020-1-1")

......
};

    qDebug()<<this->staticMetaObject.indexOfClassInfo("时间");//1

6、int constructorCount()

返回此类中构造函数的数目。构造函数加上 Q_INVOKABLE 宏才能被元对象系统识别。

class Widget : public QWidget
{
    Q_OBJECT

public:
    Q_INVOKABLE Widget(QWidget *parent = nullptr);
    ~Widget();

......

7、QMetaMethod constructor(int index)

返回具有给定索引的构造函数的元数据。

8、int indexOfConstructor(const char *constructor)

查找构造函数并返回其索引,找不到则返回 -1。

构造函数必须是规范化的形式,如 normalizedSignature() 返回的那样。

void Widget::on_pushButton_clicked()
{
    auto metaObject = this->staticMetaObject;
    qDebug()<<metaObject.indexOfConstructor(QMetaObject::normalizedSignature("Widget()"));
}

9、int enumeratorCount()

返回此类中的枚举数。枚举加上 Q_FLAG() 才能被元对象系统识别。

    enum test01
    {
    };
    Q_FLAG(test01)

    enum class test02
    {
    };
    Q_FLAG(test02)

    qDebug()<<this->staticMetaObject.enumeratorCount();//2

10、QMetaEnum enumerator(int index)

返回具有给定索引的枚举的元数据。

11、int enumeratorOffset()

返回此类的枚举偏移量,即此类第一个枚举的索引位置。

如果类没有带枚举的超类,则偏移量为0;否则,偏移量是类超类中所有枚举数的总和。

12、int indexOfEnumerator(const char *name)

查找枚举并返回其索引,找不到则返回 -1。

13、QMetaMethod method(int index)

返回具有给定索引的方法的元数据。加上 Q_INVOKABLE 宏的方法才能被元对象系统识别。

14、int methodCount()

返回此类中的方法数,包括所有基类提供的方法数。这包括了信号和槽。

获取包含特定于给定类的方法:

const QMetaObject* metaObject = obj->metaObject();
QStringList methods;
for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
    methods << QString::fromLatin1(metaObject->method(i).methodSignature());

15、int indexOfMethod(const char *method)

查找函数并返回其索引,找不到则返回 -1。

method 必须是规范化的形式,如由 normalizedSignature() 返回。

void Widget::on_pushButton_clicked()
{
    auto metaObject = this->staticMetaObject;
    qDebug()<<metaObject.indexOfMethod(QMetaObject::normalizedSignature("on_pushButton_clicked()"));
}

16、int methodOffset()

返回此类的方法偏移量,即该类第一个成员函数的索引位置。

偏移量是类的超类中所有方法的总和。

17、int indexOfSignal(const char *signal)

查找信号并返回其索引,找不到则返回 -1。

这与 indexOfMethod() 相同,只是如果方法存在但不是信号则将返回 -1。

signal 必须是规范化的形式,如由 normalizedSignature() 返回。

18、int indexOfSlot(const char *slot)

查找槽并返回其索引,找不到则返回 -1。

这与 indexOfMethod() 相同,只是如果该方法存在但不是槽则将返回-1。

19、QMetaProperty property(int index)

返回具有给定索引的属性的元数据。属性使用 Q_PROPERTY 宏定义。

20、int indexOfProperty(const char *name)

查找属性并返回其索引,找不到则返回 -1。

class Widget : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(int test READ getTest WRITE setTest NOTIFY testChanged)

......
};

    auto metaObject = this->staticMetaObject;
    qDebug()<<metaObject.indexOfProperty("test");

21、int propertyCount()

返回此类中的属性数,包括所有基类提供的属性数。

获取包含特定于给定类的属性:

const QMetaObject* metaObject = obj->metaObject();
QStringList properties;
for(int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i)
    properties << QString::fromLatin1(metaObject->property(i).name());

22、int propertyOffset()

返回此类的属性偏移量,即此类第一个属性的索引位置。偏移量是类的超类中所有属性的总和。

23、bool inherits(const QMetaObject *metaObject)

当前 QMetaObject 描述的类是否继承 metaObject 所描述的类型。类型被视为继承自身。

24、QMetaType metaType()

返回与此元对象对应的元类型。

namespace test
{
class testClass : public QObject
{
    Q_OBJECT
public:
    testClass() = default;
};
}

class Widget : public QWidget
{
    Q_OBJECT

......
};


void Widget::on_pushButton_clicked()
{
    qDebug()<<this->staticMetaObject.metaType().name(); //Widget
    test::testClass t1;
    qDebug()<<t1.staticMetaObject.metaType().name(); //test::testClass
}

25、QObject * newInstance(QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), ......)

构造此类的新实例。最多可以向构造函数传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8、val9)。

返回新对象,如果没有合适的构造函数,则返回nullptr。

要注意只有使用 Q_INVOKABLE 宏声明的构造函数才能通过元对象系统使用。

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    Widget w;
//    w.show();
    if(Widget * w = qobject_cast<Widget*>(Widget::staticMetaObject.newInstance()))
    {
        w->show();
    }

    return a.exec();
}

26、const QMetaObject * superClass()

返回超类的元对象,如果没有此类对象,则返回nullptr。

27、QMetaProperty userProperty()

返回 USER 标志设置为 true 的属性。见:Qt属性系统

四、宏成员

1、QGenericArgument Q_ARG(Type, const Type &value)

此宏接受 Type 和对该类型值的常量引用,并返回可以传递给 QMetaObject::invokeMethod() 的 QGenericArgument 对象。

2、QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)

此宏接受 Type 和对该类型值的非常量引用,并返回可以传递给 QMetaObject::invokeMethod() 的QGenericReturnArgument 对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值