(八)C++与QML混合编程----在C++中使用QML对象

Qt最核心的一个基础特性,就是元对象系统,通过元对象系统,你可以查询QObject的某个派生类的类名,有哪些信号槽,属性,可调用方法等信息,然后也可以使用QMetaObject::invokeMethod()调用QObject的某个注册到元对象系统中的方法。而对于使用Q_PROPERTY定义的属性,可以使用QObject的property()方法访问属性,如果该属性定义了WRITE方法,还可以使用setProperty()修改属性。所以,只要我们找到QML环境中的某个对象,就可以通过元对象系统来访问它的属性、信号、槽等。

查找一个对象的孩子

QObject类的构造函数有一个parent参数,可以指定一个对象的父亲,QML中的对象其实借助这个组成了以根Item为根的一颗对象树。而QObject定义了一个属性objectName,这个对象名字属性,就可以用于查找对象。查找对象的方法有findChild()和findChildren():

template<typename T>
inline T findChild(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
    typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
    return static_cast<T>(qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options));
}

template<typename T>
inline QList<T> findChildren(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
    typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
    QList<T> list;
    qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject,  reinterpret_cast<QList<void *> *>(&list), options);
    return list;
}

使用元对象调用QML对象的方法

QMetaObject的invokeMethod()方法用来调用一个对象的信号、槽、可调用的方法,它是一个静态方法:

static bool invokeMethod(QObject *obj, const char *member,
                         Qt::ConnectionType,
                         QGenericReturnArgument ret,
                         QGenericArgument val0 = QGenericArgument(Q_NULLPTR),
                         QGenericArgument val1 = QGenericArgument(),
                         QGenericArgument val2 = QGenericArgument(),
                         QGenericArgument val3 = QGenericArgument(),
                         QGenericArgument val4 = QGenericArgument(),
                         QGenericArgument val5 = QGenericArgument(),
                         QGenericArgument val6 = QGenericArgument(),
                         QGenericArgument val7 = QGenericArgument(),
                         QGenericArgument val8 = QGenericArgument(),
                         QGenericArgument val9 = QGenericArgument());

obj:被调用对象的指针
memeber:被调用对象的方法名字
connectType:连接类型,和connect最后一个参数一样
ret:方法返回值
val0,val1…:传递给被调用方法的参数
假设一个对象有一个槽QString slotFunc(QString,int,double),那么调用方式为:

QString ret;
QMetaObject::invokeMethod(obj,"slotFunc",Qt::DirectConnection,
									Q_RETURN_ARG(QString,retVal)Q_ARG(QString,"sqrt"),
									Q_ARG(int,11),
									Q_ARG(double,12.7)

示例

main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.2

Window {
   objectName: "rootObject";
   width: 360;
   height: 360;
   visible: true;

   Text {
       objectName: "textLabel";
       text: "Hello World";
       anchors.centerIn: parent;
       font.pixelSize: 26;
   }
   Button {
       anchors.right: parent.right;
       anchors.rightMargin: 4;
       anchors.bottom: parent.bottom;
       text: "quit";
       objectName: "quitButton";
   }

}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQuickView>
#include <QtQml>
#include "changeqmlcolor.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

	QQmlApplicationEngine engine;
	engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
	if (engine.rootObjects().isEmpty())
		return -1;

	QObject *root = nullptr;
	QList<QObject*> rootObjects = engine.rootObjects();
	int count = rootObjects.size();
	for (int i = 0; i < count; i++)
	{
		if (rootObjects.at(i)->objectName() == "rootObject")
		{
			root = rootObjects.at(i);
			break;
		}
	}
	new ChangeQmlColor(root);
	QObject* quitButton = root->findChild<QObject*>("quitButton");
	if (quitButton)
	{
		QObject::connect(quitButton, SIGNAL(clicked()), &app, SLOT(quit()));
	}
	QObject* textLabel = root->findChild<QObject*>("textLabel");
	if (textLabel)
	{
		bool bRet = QMetaObject::invokeMethod(textLabel, "setText", Q_ARG(QString, "world hello"));
		qDebug() << "call setText return -" << bRet;
		textLabel->setProperty("color", QColor::fromRgb(255, 0, 0));
		bRet = QMetaObject::invokeMethod(textLabel, "doLayout");
		qDebug() << "call doLayout return -" << bRet;
	}
    return app.exec();
}

在这里插入图片描述
控制台输出为:
QMetaObject::invokeMethod: No such method QQuickText::setText(QString)
call setText return - false
call doLayout return - true
可以看出Text对象对应于QQuickText类,而QQuickText类没有setText方法,因此调用setText方法失败。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vegetablesssss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值