C++與QML進(jìn)行數(shù)據(jù)交互的常見(jiàn)方法總結(jié)
一、屬性綁定
這是最簡(jiǎn)單的方式,可以在QML中直接綁定C++ 對(duì)象的屬性。通過(guò)在C++ 對(duì)象中使用Q_PROPERTY宏定義屬性,然后在QML中使用綁定語(yǔ)法將屬性與QML元素關(guān)聯(lián)起來(lái)。
1.person.h
#include <QObject> class Person : public QObject { Q_OBJECT /* 使用 Q_PROPERTY 定義交互的屬性 */ Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged) Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged) public: explicit Person(QObject *parent = nullptr) : QObject(parent), m_name(""), m_age(0) { } /* 為屬性提供 getter 和 setter 方法 */ QString getName() const { return m_name; } void setName(const QString& name) { m_name = name; emit nameChanged(); } int getAge() const { return m_age; } void setAge(int age) { m_age = age; emit ageChanged(); } signals: /* 信號(hào)與屬性對(duì)應(yīng),通過(guò)信號(hào)通知其他對(duì)象屬性的變化 */ void nameChanged(); void ageChanged(); private: QString m_name; int m_age; };
2.main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "person.h" int main(int argc, char *argv[]) { /* 啟用Qt應(yīng)用程序的高DPI縮放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 創(chuàng)建一個(gè)Qt應(yīng)用程序的實(shí)例 */ QGuiApplication app(argc, argv); // 創(chuàng)建Person對(duì)象 Person person; QQmlApplicationEngine engine; /* 將Person對(duì)象作為QML上下文屬性 */ engine.rootContext()->setContextProperty("person", &person); const QUrl url(QStringLiteral("qrc:/main.qml")); /* 將 QQmlApplicationEngine 對(duì)象的 objectCreated 信號(hào)連接到一個(gè) lambda 函數(shù)上 */ /* lambda 函數(shù)用于在 QML 文件中的根對(duì)象被創(chuàng)建時(shí)進(jìn)行處理,檢查對(duì)象是否成功創(chuàng)建,如果創(chuàng)建失敗則退出應(yīng)用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加載QML文件并顯示用戶界面 */ engine.load(url); return app.exec(); }
3.main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") Column { spacing: 10 TextField { placeholderText: "請(qǐng)輸入姓名" text: person.name // 與Person對(duì)象的name屬性綁定 onTextChanged: person.name = text // 當(dāng)文本改變時(shí),更新Person對(duì)象的name屬性 } Slider { from: 0 to: 100 value: person.age // 與Person對(duì)象的age屬性綁定 onValueChanged: person.age = value // 當(dāng)滑塊值改變時(shí),更新Person對(duì)象的age屬性 } Text { text: "姓名:" + person.name } Text { text: "年齡:" + person.age } } }
二、信號(hào)與槽
C++ 對(duì)象可以發(fā)出信號(hào),而QML中的元素可以連接到這些信號(hào)上。這樣,當(dāng)C++ 對(duì)象的狀態(tài)發(fā)生變化時(shí),可以通過(guò)信號(hào)與槽機(jī)制將這些變化傳遞給QML界面。
1.myobject.h
#include <QObject> #include <QtDebug> class MyObject : public QObject { Q_OBJECT public: explicit MyObject(QObject *parent = nullptr) : QObject(parent) {} signals: void mySignal(QString message); public slots: void mySlot(const QString& message) { qDebug() << "Received message from QML:" << message; emit mySignal("Hello from C++");} };
2.main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "myobject.h" int main(int argc, char *argv[]) { /* 啟用Qt應(yīng)用程序的高DPI縮放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 創(chuàng)建一個(gè)Qt應(yīng)用程序的實(shí)例 */ QGuiApplication app(argc, argv); /* 將自定義 C++ 類型注冊(cè)到 QML 中的函數(shù), 將自定義 C++ 類型注冊(cè)到 QML 中的函數(shù) */ qmlRegisterType<MyObject>("com.example", 1, 0, "MyObject"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); /* 將 QQmlApplicationEngine 對(duì)象的 objectCreated 信號(hào)連接到一個(gè) lambda 函數(shù)上 */ /* lambda 函數(shù)用于在 QML 文件中的根對(duì)象被創(chuàng)建時(shí)進(jìn)行處理,檢查對(duì)象是否成功創(chuàng)建,如果創(chuàng)建失敗則退出應(yīng)用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加載QML文件并顯示用戶界面 */ engine.load(url); return app.exec(); }
3.main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 import com.example 1.0 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") /* 定義 sendToCpp 信號(hào) */ signal sendToCpp(string message) /* Connections 組件用于連接 myObject 的 onMySignal 信號(hào) */ Connections { target: myObject onMySignal: console.log("Received message from C++:", message) } MyObject { id: myObject /* 將 onMySignal 信號(hào)傳遞到 sendToCpp信號(hào)上,便于 QML 處理 */ onMySignal: sendToCpp(message) } Button { text: "Send message to C++" anchors.centerIn: parent /* 單擊按鈕時(shí),會(huì)將信號(hào)傳遞到 C++ 的 mySlot 槽上 */ onClicked: myObject.mySlot("Hello from QML") } }
三、模型視圖
模型視圖(Model-View):可以使用C++ 中的數(shù)據(jù)模型(QStandardItemModel)來(lái)提供數(shù)據(jù)給QML界面。QML中的視圖元素(如ListView或GridView)可以使用這些模型來(lái)顯示數(shù)據(jù)。
1.mymodel.h
#ifndef MYMODEL_H #define MYMODEL_H #include <QAbstractListModel> #include <QList> class MyModel : public QAbstractListModel { Q_OBJECT public: explicit MyModel(QObject *parent = nullptr); enum { NameRole = Qt::UserRole + 1, AgeRole, EmailRole }; // 重寫(xiě)以下幾個(gè)虛函數(shù) int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash<int, QByteArray> roleNames() const override; private: struct Person { QString name; int age; QString email; }; QList<Person> m_persons; }; #endif // MYMODEL_H
2.mymodel.cpp
#include "mymodel.h" MyModel::MyModel(QObject *parent) : QAbstractListModel(parent) { // 初始化一些數(shù)據(jù) m_persons.append({"Alice", 25, "alice@example.com"}); m_persons.append({"Bob", 30, "bob@example.com"}); m_persons.append({"Charlie", 35, "charlie@example.com"}); } int MyModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_persons.count(); } QVariant MyModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= m_persons.count() || index.row() < 0) return QVariant(); const Person &person = m_persons[index.row()]; if (role == NameRole) return person.name; else if (role == AgeRole) return person.age; else if (role == EmailRole) return person.email; return QVariant(); } QHash<int, QByteArray> MyModel::roleNames() const { QHash<int, QByteArray> roles; roles[NameRole] = "name"; roles[AgeRole] = "age"; roles[EmailRole] = "email"; return roles; }
3.main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "mymodel.h" int main(int argc, char *argv[]) { /* 啟用Qt應(yīng)用程序的高DPI縮放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 創(chuàng)建一個(gè)Qt應(yīng)用程序的實(shí)例 */ QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyModel myModel; engine.rootContext()->setContextProperty("myModel", &myModel); const QUrl url(QStringLiteral("qrc:/main.qml")); /* 將 QQmlApplicationEngine 對(duì)象的 objectCreated 信號(hào)連接到一個(gè) lambda 函數(shù)上 */ /* lambda 函數(shù)用于在 QML 文件中的根對(duì)象被創(chuàng)建時(shí)進(jìn)行處理,檢查對(duì)象是否成功創(chuàng)建,如果創(chuàng)建失敗則退出應(yīng)用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加載QML文件并顯示用戶界面 */ engine.load(url); return app.exec(); }
4.main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") ListView { anchors.fill: parent model: myModel delegate: Item { width: parent.width height: 60 Column { Text { text: name } Text { text: age } Text { text: email } } } } }
運(yùn)行效果
四、QML類型注冊(cè)
QML類型注冊(cè)(QML Type Registration):可以將C++ 對(duì)象注冊(cè)為自定義的QML類型,使得QML可以直接創(chuàng)建和使用這些對(duì)象。通過(guò)在C++ 中使用 Q_PROPERTY 宏和 Q_INVOKABLE 函數(shù),可以將C++ 類注冊(cè)為QML類型。我需要這樣一個(gè)案例
1.myobject.h
#include <QQmlEngine> #include "QDebug" class MyObject : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) public: explicit MyObject(QObject *parent = nullptr) : QObject(parent) {} QString name() const { return m_name; } void setName(const QString &name) { m_name = name; emit nameChanged(); } Q_INVOKABLE void printName() { qDebug() << "Name:" << m_name; } static void registerQmlType() { qmlRegisterType<MyObject>("com.example", 1, 0, "MyObject"); } signals: void nameChanged(); private: QString m_name; };
2.main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "myobject.h" int main(int argc, char *argv[]) { /* 啟用Qt應(yīng)用程序的高DPI縮放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 創(chuàng)建一個(gè)Qt應(yīng)用程序的實(shí)例 */ QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyObject::registerQmlType(); const QUrl url(QStringLiteral("qrc:/main.qml")); /* 將 QQmlApplicationEngine 對(duì)象的 objectCreated 信號(hào)連接到一個(gè) lambda 函數(shù)上 */ /* lambda 函數(shù)用于在 QML 文件中的根對(duì)象被創(chuàng)建時(shí)進(jìn)行處理,檢查對(duì)象是否成功創(chuàng)建,如果創(chuàng)建失敗則退出應(yīng)用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加載QML文件并顯示用戶界面 */ engine.load(url); return app.exec(); }
3.main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 import com.example 1.0 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") MyObject { id: myObject name: "John" } /* 垂直布置組件 */ Column { anchors.fill: parent // 大小為父組件的大小 anchors.margins: 40 // 與父組件四周的間隔 spacing: 10 // 子組件之間的間隔 Text { text: myObject.name } Button { text: "Print Name" onClicked: myObject.printName() } } }
到此這篇關(guān)于C++與QML進(jìn)行數(shù)據(jù)交互的常見(jiàn)方法總結(jié)的文章就介紹到這了,更多相關(guān)C++ QML數(shù)據(jù)交互內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
實(shí)例分享cmake編譯一個(gè)簡(jiǎn)單c++項(xiàng)目(demo)
下面通過(guò)一個(gè)小例子來(lái)說(shuō)明cmake編譯一個(gè)c++項(xiàng)目,生成可執(zhí)行文件,需要的朋友可以參考下2020-02-02C語(yǔ)言數(shù)組和指針,內(nèi)存之間的關(guān)系
這篇文章主要介紹了C語(yǔ)言數(shù)組和指針,內(nèi)存之間的關(guān)系,首先論證一維數(shù)組和一級(jí)指針之前的關(guān)系,我們常常使用一級(jí)指針指針的方式訪問(wèn)一維數(shù)組,只有對(duì)內(nèi)存的理解到位才能理解它們直接的關(guān)系。需要的小伙伴可以參考一下2022-02-02Sersync+Rsync實(shí)現(xiàn)觸發(fā)式文件同步實(shí)戰(zhàn)過(guò)程
sersync是使用c++編寫(xiě),而且對(duì)linux系統(tǒng)文 件系統(tǒng)產(chǎn)生的臨時(shí)文件和重復(fù)的文件操作進(jìn)行過(guò)濾。下面通過(guò)本文給大家分享Sersync+Rsync實(shí)現(xiàn)觸發(fā)式文件同步實(shí)戰(zhàn)過(guò)程,需要的朋友參考下吧2017-09-09C語(yǔ)言實(shí)現(xiàn)猜數(shù)字大小的游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)猜數(shù)字大小的游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01pcl1.8.0+vs2013環(huán)境配置超詳細(xì)教程
這篇文章主要介紹了pcl1.8.0+vs2013環(huán)境配置超詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07C語(yǔ)言編程之動(dòng)態(tài)內(nèi)存與柔性數(shù)組的了解
本文是C語(yǔ)言編程篇,這篇文章主要為大家介紹了C語(yǔ)言編程中動(dòng)態(tài)內(nèi)存的函數(shù)與柔性數(shù)組的特點(diǎn),有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09盤(pán)點(diǎn)分析C語(yǔ)言中少見(jiàn)卻強(qiáng)大的字符串函數(shù)
這篇文章主要為大家盤(pán)點(diǎn)及分析C語(yǔ)言中少見(jiàn)卻強(qiáng)大的字符串函數(shù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02MongoDB?C?驅(qū)動(dòng)程序安裝(libmongoc)?和?BSON?庫(kù)(libbson)方法
這篇文章主要介紹了安裝?MongoDB?C?驅(qū)動(dòng)程序?(libmongoc)?和?BSON?庫(kù)?(libbson),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09