簡體   English   中英

QML 單調樣式嵌套文件

[英]QML singletone style nested files

我已經為 QML 應用程序定義了樣式作為單獨的文件MyStyle.qml

pragma Singleton
import QtQuick 2.15
import QtQml 2.15

QtObject {
    property color color1: "#ffffff"
    ...
}

我想用另一個超分辨率文件修改它 >2k MyStyle_2k.qml

MyStyle{
    color1: "#000000"
    ... 
}

樣式在main.cpp中注冊:

QScreen* screen = QGuiApplication::primaryScreen();
auto screenHeight = screen->geometry().height();

QUrl styleUrl;

if(screenHeight > 1440){
    styleUrl = QUrl("qrc:/gui/style/MyStyle_2k.qml");
}else{
    styleUrl = QUrl("qrc:/gui/style/MyStyle.qml");
}

qmlRegisterSingletonType(styleUrl, "MyStyle", 1, 0, "MyStyle");

不幸的是,由於錯誤,它不起作用:

QQmlApplicationEngine 無法加載組件 qrc:/path/other_file.qml: Type MyStyle/MyStyle unavailable:9:1: Composite Singleton Type MyStyle 不可創建。

是否可以通過另一個文件修改 qml singleton?

您正在嘗試創建 singleton 類型的實例,這是不可能的,因此會出現錯誤消息。 如果你想創建樣式的實例並在 QML 中修改它,你需要使用 qmlRegisterType()。

或者你需要寫MyStyle.color1: "#000000"來修改 singleton 的值。

編輯:您可以創建一個可實例化的樣式,如InternalMyStyle.qml ,在那里設置所有默認值,然后在MyStyle.qmlMyStyle_2k.qml中重新使用它,如下所示。 MyStyle.qmlMyStyle_2k.qml仍然是單例。

InternalMyStyle.qml

import QtQuick

QtObject {
    property color color1: "#ff00ff"
}

我的風格.qml

pragma Singleton
import QtQuick

InternalMyStyle {}

我的風格_2k.qml

pragma Singleton
import QtQuick

InternalMyStyle {
    color1: "#ff0000"
}

主.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QScreen>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QScreen *screen = QGuiApplication::primaryScreen();
    auto screenHeight = screen->geometry().height();

    QUrl styleUrl;

    if (screenHeight > 1440)
        styleUrl = QUrl(u"qrc:/untitledMyStyle/MyStyle_2k.qml"_qs);
    else
        styleUrl = QUrl(u"qrc:/untitledMyStyle/MyStyle.qml"_qs);

    qmlRegisterSingletonType(styleUrl, "MyStyle", 1, 0, "MyStyle");

    QQmlApplicationEngine engine;
    const QUrl url(u"qrc:/untitledMyStyle/main.qml"_qs);
    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();
}

CMakeLists.txt

...
qt_add_qml_module(appuntitledMyStyle
    URI untitledMyStyle
    VERSION 1.0
    QML_FILES
        main.qml
        MyStyle.qml
        MyStyle_2k.qml
        InternalMyStyle.qml
)
...

您應該將這兩個文件命名為MyStyle.qml ,但按以下方式組織它們:

qrc:/gui/style/MyStyle.qml
qrc:/gui/style/+highres/MyStyle.qml

然后,您可以通過使用文件選擇器讓 Qt 知道要加載哪個版本的MyStyle.qml 請注意加號+作為highres前綴的用法。 這就是 Qt 基於默認或自定義文件選擇器組織文件覆蓋的方式。 QT_FILE_SELECTOR highres變量,例如

QScreen* screen = QGuiApplication::primaryScreen();
auto screenHeight = screen->geometry().height();
if (screenHeight > 1440) {
   qputenv("QT_FILE_SELECTOR", QString("highres").toUtf8());
}

此代碼需要在您的main.cpp中盡早發生,因為QT_FILE_SELECTOR將被檢查一次並且以后不會被重新檢查。

來自https://doc.qt.io/qt-6/qfileselector.html

將從 QT_FILE_SELECTORS 環境變量中添加更多選擇器,設置后應該是一組逗號分隔的選擇器。 注意這個變量只會被讀取一次; 如果變量在應用程序運行時發生變化,選擇器可能不會更新。 初始選擇器集僅在首次使用時評估一次。

如果您不想使用QT_FILE_SELECTOR環境變量,那么,為 QML 使用定義文件選擇器的正確方法是通過 QQmlFileSelector:

QScreen* screen = QGuiApplication::primaryScreen();
auto screenHeight = screen->geometry().height();
QQmlFileSelector* selector = null;
if (screenHeight > 1440) {
   selector = new QQmlFileSelector(&engine);
   selector->setExtraSelectors(QStringList() << QString("highres"));
}

使用QQmlFileSelector的優點是您可以控制在運行時處於活動狀態的文件選擇器。 即您可以添加/刪除文件選擇器。 然而,這也意味着每次更改文件選擇器時,都必須強制重新加載已經加載的組件。 但是,它是以額外的編碼要求為代價的,因為您需要實例化 QQmlFileSelector 配置它,強制重新加載組件(這對於單例來說更難),並在程序退出時清理代碼(注意我沒有提供任何這些,因為如何實例化和發布 QQmlFileSelector 與您在應用程序中管理 memory 的方式一致,這取決於您。

有關更多詳細信息,您應該直接查閱文檔。

我找到的唯一可行的解決方案是使用單個文件作為 singleton Style.qml 和 state 組。

主.cpp

...
QScreen* screen = QGuiApplication::primaryScreen();
auto screenHeight = screen->geometry().height();

    if(screenHeight > 1440){
        engine.rootContext()->setContextProperty("StyleState", "2k");
    }else{
        engine.rootContext()->setContextProperty("StyleState", "");
    }
...

State.qml

pragma Singleton
import QtQuick 2.15
import QtQml 2.15

QtObject {
    id: root

    property var widthA: 50
    property var widthB: 100
    
    property alias customStyle: customState.state // alias for call dircectly from qml

    property var states: StateGroup{
        id: customState
        state: StyleState
        states: [
            State{
                name: "2k"
                PropertyChanges{
                    target: root
                    widthA: 100
                    widthB: 200
                }
            }
        ]
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM