QT的C++和QML框架中,後端的C++程序,對於前端的QML程序來說,它實際上是QML程序的服務器,在QT的官方推薦文檔中,採用瞭如下方法來實現C++程序的註冊:
qmlRegisterType<BackEnd>("io.qt.examples.backend", 1, 0, "BackEnd");
其中:
- io.qt.examples.backend 是QML文件中需要引用的QML的包名;
- 1 是大版本號;
- 0 是小版本號;
- BackEnd 是C++生成的QML對象,以使在QML文件中,對C++生成的QML對象進行操作;
同時在QML文件中需要引入
import io.qt.examples.backend 1.0
但這種方法,總感覺有點彆扭,主要是因爲:
- C++作爲後臺的服務器,幹嘛要註冊成爲一個QML的組件?
- C++註冊的QML組件,如果在多個QML中使用,會不會實現了多個實例化,也就是說出現了多個服務器,如果是並行處理也就算了,如果是單一服務器,如何保證它們之間的數據同步
- 如果在C++的程序裏面,定義了對象,對象中又定義了對象;那麼在QML中如要對底層對象的屬性和方法進行調用,豈不是特別麻煩?
實際上,QT還有另外一種方式,來註冊C++的程序:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QIcon>
#include <QQuickStyle>
#include <QQmlContext>
#include "corecalculate.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// 本地存儲設置
app.setOrganizationName("weisuansuan");
app.setOrganizationDomain("weisuansuan.top");
app.setApplicationName("WeiSuanSuan Application");
// 設置icon
QIcon::setThemeName("weisuansuan");
// 設置樣式
QQuickStyle::setStyle("Material");
// 設置後臺程序
QQmlContext *ctx = engine.rootContext();
CoreCalculate core;
ctx->setContextProperty("myCore", &core);
ctx->setContextProperty("myLoan", &core.loan);
ctx->setContextProperty("myModel", &core.mylistModel);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
這裏在C++程序中,首先引入頭文件:
#include <QQmlContext>
獲取QMLContext對象
QQmlContext *ctx = engine.rootContext();
實例化C++對象
CoreCalculate core;
對C++對象的不同部分,進行分別註冊
ctx->setContextProperty("myCore", &core);
ctx->setContextProperty("myLoan", &core.loan);
ctx->setContextProperty("myModel", &core.mylistModel);
在QML文件中,不需要引入文件,直接可以對
- myCore
- myLoan
- myModel
進行操作;在QML中,它們是獨立的,沒有任何關係,後臺的C++對象core,保證了它們的數據同步。
參見課程 《QT QML跨平臺移動APP編程》 有詳細的解答