C++通过函数访问QML
一、基本使用
1、QML
function setValue(value) { if(value>1 || value<0) { return; } pen.score = value; pen.requestPaint(); }
2、C++
#include <QMetaObject>
QObject *root = ui->quickWidget->rootObject();
QMetaObject::invokeMethod(root, "setValue", Q_ARG(QVariant, QVariant(0.8)));
Q_ARG是入参,如果需要接收返回值用Q_RETURN_ARG(QVariant, returnedValue)
二、访问QML里的函数
如qml里有多个方块,每个方块有多个属性,怎么在c++里设置这些属性呢?可以通过:
①、动态绑定每一个参数【很麻烦,工作量也大】;
②、把每个方块的信息存入json里,再通过objectname获取到每一个方块,再通过function传入json字符串,由qml在function内部完成json解析获取对应参数;
③、。。
这里使用第二种方式
1、封装每个方块,主要由两个参数:nodeid和name
MyNode.qml
import QtQuick 2.0 Rectangle { id:rect; width: 50; height: 50; radius: 10; color: "green"; property string node_id: ""; property string name: ""; function setColor(color) { rect.color = color; } function setNodeInfo(info)//传入json { // var json = '{"nodeId":"123", "name":"雷达主机"}'; var obj = JSON.parse(info); console.log(obj.nodeId); console.log(obj.name); console.log(obj); node_id = obj.nodeId; name = obj.name; } MouseArea { anchors.fill: parent; onClicked: { console.log(node_id,name); } } }
2、主qml
import QtQuick 2.7 Rectangle { width: 600; height: 400; color: "gray"; Row { anchors.fill: parent; spacing: 10; MyNode { id: rect1; objectName: "rect1"; } MyNode { id: rect2; objectName: "rect2"; } MyNode { id: rect3; objectName: "rect3"; } } }
3、main.cpp
QUrl source("qrc:/qml/qml/Test.qml"); ui->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView ); ui->quickWidget->setSource(source); ui->quickWidget->setClearColor(QColor(Qt::transparent)); QObject *root = ui->quickWidget->rootObject();//根qml QObject *pRect = root->findChild<QObject *>("rect1");//第一个方块 QMetaObject::invokeMethod(pRect, "setColor", Q_ARG(QVariant, QVariant("red")));//设置颜色 QMetaObject::invokeMethod(pRect, "setNodeInfo", Q_ARG(QVariant, QVariant("{\"nodeId\":\"123\", \"name\":\"雷达主机\"}")));//设置值,注意双引号需要转义
核心就是获取到方块指针,然后invoke函数,传入json,在qml里解析,这种方式应该效率不太高,因为我们希望所有解析都在c++里做
三、设置组件基本属性
如果QML里有一个Rectangle,Rectangle是有很多属性的,如大小、位置、颜色等,我们可以在C++里直接设置这些属性,通过setProperty函数:
例子:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlComponent> #include <QQuickWindow> #include <QQuickView> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); // 1. 使用 QQmlApplicationEngine // QQmlApplicationEngine engine; // const QUrl url(QStringLiteral("qrc:/main.qml")); // engine.load(url); // QObject *rect = engine.rootObjects().at(0)->findChild<QObject*>("rect"); // if (rect) // rect->setProperty("color", "red"); // 2. 使用 QQmlEngine + QQmlComponent // QQmlEngine engine; // QQmlComponent *component = new QQmlComponent(&engine); // component->loadUrl(QUrl("qrc:/main.qml")); // QObject *topLevel = component->create(); // QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel); // window->show(); // QObject *rect = topLevel->findChild<QObject*>("rect"); // if (rect) // rect->setProperty("color", "red"); // 3. 使用 QQuickView QQuickView *view = new QQuickView; view->setSource(QUrl("qrc:/main.qml")); view->show(); QObject *rect = view->findChild<QObject*>("rect"); if (rect) rect->setProperty("color", "red"); //4.使用QQucikWidget //QObject *root = ui->quickWidget->rootObject();//根qml //QObject *pRect = root->findChild<QObject *>("rect1");//第一个方块 //if (rect){ // rect->setProperty("color", "red"); //} return app.exec(); } import QtQuick 2.12 import QtQuick.Window 2.12 Item { visible: true width: 640 height: 480 Rectangle { objectName: "rect" anchors.fill: parent color: "yellow" } }
主要原理就是先获取这个QML对象,转成C++里的QObject*,然后通过setProperty函数进行属性设置,代码参考:https://blog.csdn.net/qq_34139994/article/details/105195447
PS:
例子1:
QVariant invokeRet; //qml函数返回值 bool ret = QMetaObject::invokeMethod(m_parent, "createOneMarkLine", Qt::AutoConnection, Q_RETURN_ARG(QVariant, invokeRet), Q_ARG(QVariant, QVariant(o)), Q_ARG(QVariant, QVariant(i*10))); if(ret){ QQuickItem* markLine = (QQuickItem*)invokeRet.value<QQuickItem*>();//创建成功的对象
}
else{
qDebug()<<"err";
}
createOneMarkLine是qml里封装的函数,输入两个int,返回一个Item也就是对应Qt里的QQuickItem*对象。
长风破浪会有时,直挂云帆济沧海!
可通过下方链接找到博主
https://www.cnblogs.com/judes/p/10875138.html