QML調用C++
思路
一種解決方案:
使用Qt中的QML調用C++中的類,首先使用需要定義一個繼承自 QObject
的類,然后將這個類注冊到 QML 中去,然后在這個類使用 Q_INVOKABLE
這個宏修飾的函數,都可以直接在QML中調用。
示例:
## 0x01 定義一個C++類
#include <QObject>
#include <QDebug>
class QmlBrg : public QObject
{
Q_OBJECT
public:
explicit QmlBrg(QObject *parent = nullptr);
Q_INVOKABLE void ssss() const noexcept { qDebug() << "qml確實調我了!"; }
signals:
};
## 0x02 注冊到QML中去
QmlBrg* qbrg = new QmlBrg;
/** 在QML中這個實例名就叫 cbrg **/
qmlwid->rootContext()->setContextProperty("cbrg", qbrg);
### 0x03 在QML中調用
onClicked: {
console.log("我要調用 C++ !")
cbrg.ssss();
}
C++調用 QML
https://blog.csdn.net/baidu_33850454/article/details/81941675
1.1通過 objectName 來獲取QML對象
假設MyItem.qml的內容如下,Item中存在一個objectName為“rect”的矩形
import QtQuick 2.0
Item {
width: 100; height: 100
Rectangle {
anchors.fill: parent
objectName: "rect"
}
}
則 上述 矩形可以通過 如下方式獲取:
QObject *rect = object->findChild<QObject*>("rect");
if (rect)
rect->setProperty("color", "red");
如果存在多個objectName相同的對象,比如listView的Delegate中設置了一個特定的對象名稱,則可以使用QObject::findChildren()來獲取所有子對象。
警告: 盡管可以從C++中獲取和操作QML對象,但是除非為了測試和原型設計,並不建議這樣做。因為QML和C ++集成的優勢之一是能夠在QML中實現與C ++邏輯和后端分離的UI。
1.2從C ++訪問QML對象類型的成員
在QML中使用property聲明的屬性可以在C++中被獲取。假設MyItem.qml的內容如下:
// MyItem.qml
import QtQuick 2.0
Item {
property int someNumber: 100
}
則someNumber屬性值可以通過QQmlProperty,QObject::setProperty() 和QObject::property()來訪問。
QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();
qDebug() << "Property value:" << QQmlProperty::read(object, "someNumber").toInt();
QQmlProperty::write(object, "someNumber", 5000);
qDebug() << "Property value:" << object->property("someNumber").toInt();
object->setProperty("someNumber", 100);
注意:你必須通過QObject::setProperty(), QQmlProperty or QMetaProperty::write()這三種方法來設置QML的屬性,才能夠保證QML引擎對你的修改可知。
2、調用QML函數
所有的QML函數都暴露在Qt元對象系統中,可以被C++使用QMetaObject::invokeMethod()來訪問。向QML傳遞的函數參數和QML的返回值需要在C ++中轉換為QVariant值,因為這是QML函數參數和返回值的通用數據類型。例如:
// MyItem.qml
import QtQuick 2.0
Item {
function myQmlFunction(msg) {
console.log("Got message:", msg)
return "some return value"
}
}
C++ 代碼如下:
// main.cpp
QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();
QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
qDebug() << "QML function returned:" << returnedValue.toString();
delete object;
13
3、連接QML信號
所有的QML信號均可以在C++中被訪問,可以像普通Qt的C++信號一樣使用。
QML信號參數為string:
// MyItem.qml
import QtQuick 2.0
Item {
id: item
width: 100; height: 100
signal qmlSignal(string msg)
MouseArea {
anchors.fill: parent
onClicked: item.qmlSignal("Hello from QML")
}
}
C++處理方式如下:
class MyClass : public QObject
{
Q_OBJECT
public slots:
void cppSlot(const QString &msg) {
qDebug() << "Called the C++ slot with message:" << msg;
}
};
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
QObject *item = view.rootObject();
MyClass myClass;
QObject::connect(item, SIGNAL(qmlSignal(QString)),
&myClass, SLOT(cppSlot(QString)));
view.show();
return app.exec();
}
需要注意的是,當信號參數時QML對象時,參數類型應該為var,C++中槽函數的參數應該為QVariant。
QML文件如下:
// MyItem.qml
import QtQuick 2.0
Item {
id: item
width: 100; height: 100
signal qmlSignal(var anObject)
MouseArea {
anchors.fill: parent
onClicked: item.qmlSignal(item)
}
}
則C++處理方式如下:
class MyClass : public QObject
{
Q_OBJECT
public slots:
void cppSlot(const QVariant &v) {
qDebug() << "Called the C++ slot with value:" << v;
QQuickItem *item =
qobject_cast<QQuickItem*>(v.value<QObject*>());
qDebug() << "Item dimensions:" << item->width()
<< item->height();
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
QObject *item = view.rootObject();
MyClass myClass;
QObject::connect(item, SIGNAL(qmlSignal(QVariant)),
&myClass, SLOT(cppSlot(QVariant)));
view.show();
return app.exec();
}
參考鏈接:http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html