在main.cpp實例化對象調用的過程中,注冊是常見的操作之一,目前接觸到的方法有兩種,兩者的目的和使用方式是不同的,通過代碼可以直觀的
看出來:
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQGuiApplication app(argc, argv);QQmlApplicationEngine engine;//注冊方法1engine.rootContext()->setContextProperty("MyListModel", MyListModel::getInstance());//注冊方法2qmlRegisterType<MyListModel>("ListMod", 1, 0, "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();
}
qmlRegisterType
qmlRegisterType
是一個函數,用于在 QML 引擎中注冊 C++ 類型,使得 QML 文件中可以直接使用這些類型。這個函數通常在 C++ 代碼中調用,用于將自定義的 C++ 類(特別是那些繼承自 QObject
的類)暴露給 QML。
- 優點:
- QML 文件中可以直接使用注冊的類型,創建其實例,并與其進行交互。
- 支持類型安全,QML 編輯器(如 Qt Creator)可以提供自動補全和類型檢查。
- 適用于需要多個實例的情況,因為 QML 可以直接創建和管理這些實例。
- 缺點:
- 需要 C++ 類與 QML 之間進行明確的類型匹配。
- 如果類具有復雜的構造函數或需要特定的初始化邏輯,可能需要額外的設置。
在給出的例子中:
qmlRegisterType<MyListModel>("ListMod", 1, 0, "MyListModel");
這里注冊了一個名為 MyListModel
的 C++ 類,它在 QML 中的導入模塊為 “ListMod”,版本為 1.0,并且可以直接在 QML 中通過 MyListModel
類型名來創建和使用實例。
setContextProperty
setContextProperty
是一個方法,用于將 C++ 對象或值設置為 QML 上下文的屬性,這樣 QML 文件中就可以通過屬性名直接訪問它。這通常用于將單例或全局對象暴露給 QML。
- 優點:
- 簡單直接,適用于將單例或全局對象暴露給 QML。
- 不需要復雜的類型匹配或注冊。
- 缺點:
- 不支持類型安全,QML 編輯器可能無法提供自動補全或類型檢查。
- 只能在 QML 文件中訪問一個特定的實例(通常是單例)。
在給出的例子中:
engine.rootContext()->setContextProperty("MyListModel", MyListModel::getInstance());
這里將 MyListModel
的單例實例設置為 QML 上下文的屬性,名為 “MyListModel”。在 QML 文件中,可以直接通過 MyListModel
這個屬性名來訪問這個單例實例。
風險驗證
//cpp
QScreen *screen = QGuiApplication::primaryScreen();
engine.rootContext()->setContextProperty("screen_WIDTH",800);
//qml
property int screen_width: 200
width: screen_WIDTH
此時的寬度是800還是200呢?是200
總結
qmlRegisterType
用于注冊 C++ 類型,以便 QML 可以直接創建和使用這些類型的實例。setContextProperty
用于將 C++ 對象或值設置為 QML 上下文的屬性,以便 QML 可以直接訪問它們。這通常用于單例或全局對象。- 不建議使用
setContextProperty
,因為當全局和局部遇到重名時,會直接覆蓋掉,這對于程序來說是非常危險的。 - 性能方面
qmlRegisterType
會稍好一點