QML UI 与逻辑分开
前言
大多數開發者都希望創建一個可維護的應用程序,要達到該目的的方法之一就是將用戶界面與業務邏輯分開,應用程序的 UI 應該用 QML 編寫的幾個原因如下:
聲明性語言非常適合定義 UI
QML 代碼編寫很簡單,因為它比 C++更簡潔,并且不是強類型的。這也是使他成為原型的優秀語言。
JavaScript 可以很容易地在 QML 中用于響應事件。
作為一種強類型語言,C++最適合做應用程序的邏輯,通常,此類代碼執行復雜計算或數據處理等任務,這些任務在 C++中比 QML 中更快。
Qt 提供了各種在應用程序中集成 QML 和 C++的方法,前面的文章也有介紹到。典型的用例就會在用戶界面中顯示數據列表,如果數據集是靜態的,則用 QML 編寫的模型就足夠用了。
看以下示例,QML 編寫的模型示例:
將 C++用于大型或經常修改的動態數據集。
與 C++中的 QML 交互
雖然 Qt 允許從 C++中操作 QML,但是不建議這樣做,來看一個簡化的例子。
從 QML 中提取引用
假設正在為設置頁面編寫 UI:
import QtQuick 2.12 import QtQuick.Controls 2.12Page {Button {text: qsTr("Restore default settings")} }我們希望按鈕在單擊時使用 C++執行某些操作,我們知道 QML 中的對象可以像在 C++中一樣發出變化信號,因此先給按鈕定義一個 objectName,以便可以再 C++中找到它:
Button {objectName: "restoreDefaultsButton"text: qsTr("Restore default settings") }然后,在C ++中,我們找到該對象并連接到其變化信號:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QSettings>class Backend : public QObject {Q_OBJECTpublic:Backend() {}public slots:void restoreDefaults() {settings.setValue("loadLastProject", QVariant(false));}private:QSettings settings; };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;Backend backend;QObject *rootObject = engine.rootObjects().first();QObject *restoreDefaultsButton = rootObject->findChild<QObject*>("restoreDefaultsButton");QObject::connect(restoreDefaultsButton, SIGNAL(clicked()),&backend, SLOT(restoreDefaults()));return app.exec(); }#include "main.moc"通過這種方法,對象的引用從QML中“拉出”。這里是C ++邏輯層依賴于QML表示層。如果我們以這樣的方式重構QML,使得objectName更改或其他一些更改破壞了C ++找到QML對象的能力,那么我們的工作流程變得更加復雜和繁瑣。
在 QML 中調用 C++邏輯
重構 QML 比重構 C++容易得多,因此為了維護更方便,我們應該盡可能保持 C++類型不去調用 QML,然后通過將對 C++的類型的引用注冊到 QML 中來調用。
int main(int argc, char *argv[]) {QGuiApplication app(argc, argv);Backend backend;QQmlApplicationEngine engine;engine.rootContext()->setContextProperty("backend", &backend);engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;return app.exec(); }然后直接在 QML 中進行調用:
import QtQuick 2.12 import QtQuick.Controls 2.12Page {Button {text: qsTr("Restore default settings")onClicked: backend.restoreDefaults()} }這種方式,如果將來需要重構 QML,C++將保持不變。
在上面示例中,我們根據上下文設置一個 context 屬性,以將 C++對象公開給 QML 使用,這意味著屬性可提供引擎加載的每個組件使用。對于必須在加載 QML 時必須可用且不能在 QML 中實例化的對象,上下文屬性非常有用。
有關 C++類型公開給 QML 中使用的方法,之前的文章有介紹過,在這里。
總結
以上是生活随笔為你收集整理的QML UI 与逻辑分开的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QML类型系统
- 下一篇: QML 性能优化建议(一)