QML與C++交互之創(chuàng)建自定義對(duì)象的實(shí)現(xiàn)
在qml中,我們一般都是希望使用qml做界面展示,而數(shù)據(jù)處理轉(zhuǎn)由c++處理;
在此篇博客,將介紹如何在c++中給qml定義全局對(duì)象;在c++中如何定義對(duì)象給qml使用。
1 給qml定義全局對(duì)象
正常我們定義了一個(gè)qml項(xiàng)目后,main函數(shù)是這樣的:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
QQmlApplicationEngine 是 Qt 框架中用于加載和運(yùn)行基于 QML 的應(yīng)用程序的核心類,結(jié)合了 QQmlEngine 和 QQmlComponent 的功能,支持從單個(gè) QML 文件加載應(yīng)用程序,并實(shí)現(xiàn) C++ 與 QML 的雙向通信。
那么,就可以使用QQmlApplicationEngine去獲得全局上下文對(duì)象QQmlContext,通過使用上下文對(duì)象,就可以給qml設(shè)置一個(gè)全局的變量值;
獲得上下文對(duì)象:
// 獲得全局對(duì)象,上下文對(duì)象 QQmlContext *context = engine.rootContext();
給qml設(shè)置一個(gè)全局變量:
// 給qml設(shè)置一個(gè)全局變量; context->setContextProperty("SCREEN_WIDTH", 800);
這樣,就可以在qml中使用該變量了,例如在mian.qml文件內(nèi)使用:
import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.14 Window { id: root visible: true width: SCREEN_WIDTH // 直接使用 height: 500 title: qsTr("Hello World") color: "white" // 如果qml內(nèi)部有定義重名變量,那么會(huì)優(yōu)先使用qml內(nèi)部定義的變量,而不會(huì)使用C++定義的變量 //property int SCREEN_WIDTH: 500 }
注意:如果qml內(nèi)部有定義重名變量,那么會(huì)優(yōu)先使用qml內(nèi)部定義的變量;另外,定義全局變量會(huì)有性能消耗問題。
2 在c++中定義對(duì)象給qml使用
自定義C++類MyObject繼承自QObject;有兩個(gè)成員變量,int m_iValue 和 QString m_sString;并且給他倆定義get和set方法;另外在定義兩個(gè)信號(hào);最后通過Q_PROPERTY將兩個(gè)成員變量暴露給元對(duì)象。
myobject.h
#ifndef MYOBJECT_H #define MYOBJECT_H #include <QObject> class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr); // 構(gòu)造函數(shù) ~MyObject(); const int &iValue() const; void setIIValue(const int &newIValue); const QString &sString() const; void setSString(const QString &newSString); signals: void iValueChanged(); void sStringChanged(); private: int m_iValue; QString m_sString; Q_PROPERTY(int iValue READ iValue WRITE setIIValue NOTIFY iValueChanged) // Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged) // 如果值是函數(shù)內(nèi)部成員變量的值,可使用MEMBER去設(shè)置,與READ sString WRITE setSString實(shí)現(xiàn)效果一致 Q_PROPERTY(QString sString MEMBER m_sString NOTIFY sStringChanged) }; #endif // MYOBJECT_H
myobject.cpp
#include "myobject.h" MyObject::MyObject(QObject *parent) : QObject(parent) { } MyObject::~MyObject() { } const int &MyObject::iValue() const { return m_iValue; } void MyObject::setIIValue(const int &newIValue) { if (m_iValue == newIValue) { return; } m_iValue = newIValue; emit iValueChanged(); } const QString &MyObject::sString() const { return m_sString; } void MyObject::setSString(const QString &newSString) { if (m_sString == newSString) { return; } m_sString = newSString; emit sStringChanged(); }
Q_PROPERTY的參數(shù)講解
Q_PROPERTY(int iValue READ iValue WRITE setIIValue NOTIFY iValueChanged)
int iValue 指定是給qml使用的變量名,推薦與c++類成員變量名類似;
READ iValue 指的是通過iValue函數(shù)去讀取值;
WRITE setIIValue 指的是通過setIIValue函數(shù)去修改iValue值;
NOTIFY iValueChanged 指的是當(dāng)iValue值被修改后,會(huì)發(fā)送的信號(hào);
然后main函數(shù)中使用qmlRegisterType函數(shù)對(duì)自定義類進(jìn)行注冊(cè),注冊(cè)后,就可以在qml那邊導(dǎo)入使用了。
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "myobject.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // 獲得全局對(duì)象,上下文對(duì)象 QQmlContext *context = engine.rootContext(); // 給qml設(shè)置一個(gè)全局變量;如果qml內(nèi)部有定義重名變量,那么會(huì)優(yōu)先使用qml內(nèi)部定義的變量;另外,定義全局變量會(huì)有性能問題 context->setContextProperty("SCREEN_WIDTH", 800); // 注冊(cè),在需要使用的地方 import MyObj 1.0 qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
其中,MyObj是給qml那邊導(dǎo)入時(shí)使用的模塊名字,1 和 0 指的是版本,最后的MyObject就是自定義類名;
然后就可以在qml中 import MyObj 1.0 導(dǎo)入使用了。
import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.14 import MyObj 1.0 // 導(dǎo)入自定義模塊 Window { id: root visible: true width: SCREEN_WIDTH height: 500 title: qsTr("Hello World") color: "white" MyObject { iValue: 20 sString: "this is a custom obj."; Component.onCompleted: { console.log("iValue:", 20, " sString:", sString) } } }
3 番外
Q_PROPERTY為什么要指定NOTIFY信號(hào)呢?
在這里與qml的綁定有關(guān)系;
在qml中,當(dāng)給一個(gè)變量以冒號(hào)':'方式賦值時(shí),這兩個(gè)變量是互相綁定的;例如:
property int testValue: myObj.iValue
當(dāng)myObj.iValue被修改時(shí),就會(huì)觸發(fā)信號(hào)通知testValue也一并修改!
案例代碼:定義變量testValue使用冒號(hào)被myObject.iValue賦值,定義按鈕在onClicked槽函數(shù)中修改myObj.iValue值,觀察testValue是否也被修改;
import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.14 import MyObj 1.0 // 導(dǎo)入自定義模塊 Window { id: root visible: true width: SCREEN_WIDTH height: 500 title: qsTr("Hello World") color: "white" property int testValue: myObj.iValue // 綁定了 onTestValueChanged: { console.log("testValue:", testValue) } Button { width: 100; height: 50 onClicked: { myObj.iValue = 50; } } MyObject { id: myObj iValue: 20 sString: "this is a custom obj."; Component.onCompleted: { console.log("iValue:", 20, " sString:", sString) } } }
當(dāng)點(diǎn)擊按鈕后,修改的是myObj.iValue,但testValue也一并被修改了,由此證明,使用冒號(hào)賦值時(shí),他倆是會(huì)綁定在一起的。
注意,使用 = 賦值時(shí),不會(huì)有綁定的效果?。?!
到此這篇關(guān)于QML與C++交互之創(chuàng)建自定義對(duì)象的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)QML與C++交互內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C C++ 題解LeetCode2360圖中的最長(zhǎng)環(huán)示例
這篇文章主要為大家介紹了C C++ 題解LeetCode2360圖中的最長(zhǎng)環(huán)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10C++中的局部變量、全局變量、局部靜態(tài)變量、全局靜態(tài)變量的區(qū)別
本文主要介紹了C++中的局部變量、全局變量、局部靜態(tài)變量、全局靜態(tài)變量的區(qū)別。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02C語言實(shí)現(xiàn)簡(jiǎn)單的<三子棋>案例
這篇文章主要介紹了C語言實(shí)現(xiàn)簡(jiǎn)單的《三子棋》,本文通過功能區(qū)分一步步實(shí)現(xiàn)該案例,通過逐步的解析和代碼列舉,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++實(shí)現(xiàn)惡搞電腦關(guān)機(jī)小程序的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)一個(gè)簡(jiǎn)單的惡搞電腦關(guān)機(jī)小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-11-11