簡體   English   中英

從cpp動態加載和卸載2個qml文件

[英]Dynamically loading and unloading 2 qml files from cpp

我需要啟動 2 個不同的 Qml 文件“mainwindow.qml”和“basic.qml”,而兩者都是相互獨立的。

最初我需要基於標志 bSettingMainWindow 啟動 qml window,基於此我將啟動 qml 文件中的任何一個。

啟動后,我需要隨時在這 2 個 qml 文件之間切換。 它應該像加載和卸載“mainwindow.qml”和“basic.qml”,基於用戶操作。 因為因為 memory 的關注,我需要一次加載它們中的任何一個。 而且我不想玩可見的真假。

而從下面的代碼中,我可以根據標志 bSettingMainWindow 加載 qml 文件中的任何一個。 並且在加載后我可以切換到另一個 qml 文件 window。

Assume first I have launched in Mainwindow.qml then i clicked the mouse button over Rectangle of mainwindow.qml and moved to basic.qml and now if i click on the Rectangle of basic.qml it is not switching to mainwindow.qml. 反之亦然。 只有一次我可以切換這兩個黑白。我想切換多次。 以下是代碼,請求提供您的答案

//** windowLoader.hpp   **//
class WindowLoader : public QObject{
    Q_OBJECT
    QQmlApplicationEngine loadQMlEngine;

public:
    explicit WindowLoader(QObject * parent = 0);
    void loadWindow();


public slots:
    void loadMainWindow();
    void loadBasicWindow();
    void connectToMain(QObject *object = nullptr, const QUrl &url = QUrl(""));
    void connectToBasic(QObject *object = nullptr, const QUrl &url = QUrl(""));

    private:
};

//** windowLoader.cpp   **//
WindowLoader::WindowLoader(QObject *parent) : QObject(parent) {

}

void WindowLoader::loadWindow()  {
    if(bSettingMainWindow){ //this will be from a internal flag, this check is only one time during launch
        connect(&loadQMlEngine,SIGNAL(objectCreated(QObject *, const QUrl &)),this,SLOT(connectToBasic(QObject *, const QUrl &)),Qt::QueuedConnection);
        loadQMlEngine.rootContext()->setContextProperty( "interface", m_interface );
        loadQMlEngine.load(QUrl(QStringLiteral("qrc:/Qml/mainWindow.qml")));
    } else {
        connect(&loadQMlEngine,SIGNAL(objectCreated(QObject *, const QUrl &)),this,SLOT(connectToMain(QObject *, const QUrl &)),Qt::QueuedConnection);
        loadQMlEngine.rootContext()->setContextProperty( "interface", m_interface );
        loadQMlEngine.load(QUrl(QStringLiteral("qrc:/Qml/basic.qml")));     
    }
}

void WindowLoader::connectToBasic(QObject *object, const QUrl &url) {
    if(object){
        connect(object, SIGNAL(switchToBasicSignal()), this, SLOT(loadBasicWindow()));
    }
}

void WindowLoader::connectToMain(QObject *object, const QUrl &url) {
    if(object){
        connect(object, SIGNAL(switchToMainSignal()), this, SLOT(loadMainWindow()));
    }
}

void WindowLoader::loadBasicWindow() {
    loadQMlEngine.rootObjects()[0]->deleteLater();
    loadQMlEngine.destroyed();

    loadQMlEngine.rootContext()->setContextProperty( "interface", m_interface );
    loadQMlEngine.load(QUrl(QStringLiteral("qrc:/Qml/basic.qml")));
}

void WindowLoader::loadMainWindow() {
    loadQMlEngine.rootObjects()[0]->deleteLater();
    loadQMlEngine.destroyed();

    loadQMlEngine.rootContext()->setContextProperty( "interface", m_interface );
    loadQMlEngine.load(QUrl(QStringLiteral("qrc:/Qml/mainWindow.qml")));

}


//** main.cpp **//
int main( int argc, char *argv[] ) {
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
    WindowLoader root;
    root.loadWindow();
    return app.exec();
}



// ** mainWindow.qml **//
ApplicationWindow {
    visible: true
    width: 1200
    height: 800
    title: qsTr("MainWindow")

    signal switchToBasicSignal()

    Rectangle {
        anchors.fill: parent
        MouseArea{
            anchors.fill: parent
            onClicked: {
                switchToBasicSignal()
            }
        }
    }
}

//** basic.qml **//
ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("basic")

    signal switchToMainSignal()

    Rectangle {
        anchors.fill: parent
        MouseArea{
            anchors.fill: parent
            onClicked: {
                switchToMainSignal()
            }
        }
    }
}

加載和卸載完整的 window 不會提供良好的用戶體驗。 如果您有 memory 問題並且不想使用可見性屬性,您可以嘗試使用Loader概念。

我已經嘗試了下面的示例代碼,它可以工作。 基於 bool 標志,我嘗試在 windows 之間切換。 請檢查下面附上的樣本。 我希望這有助於解決您的問題。

/* main.cpp */
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "backend.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    Backend backend(&engine);

    engine.rootContext()->setContextProperty("backend", &backend);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

/* backend.h */
#ifndef BACKEND_H
#define BACKEND_H

#include <QObject>

class QQmlApplicationEngine;
class Backend : public QObject
{
    Q_OBJECT
public:
    explicit Backend(QQmlApplicationEngine *engine, QObject *parent = nullptr);

    Q_INVOKABLE void changeWindow();

private:
    QQmlApplicationEngine *_engine = nullptr;
    bool _main = true;
};

#endif // BACKEND_H

/*backend.cpp*/
#include "backend.h"
#include <QQmlApplicationEngine>
#include <QQuickWindow>

Backend::Backend(QQmlApplicationEngine *engine, QObject *parent) : QObject(parent)
{
    _engine = engine;
}

void Backend::changeWindow()
{
    QObject *qObject = _engine->rootObjects().first();
    Q_ASSERT( qObject != NULL );

    QQuickWindow* mainWindow = qobject_cast<QQuickWindow*>(qObject);
    Q_ASSERT( mainWindow );

    _main = !_main;
    if (_main)
    {
        _engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
    } else
    {
        _engine->load(QUrl(QStringLiteral("qrc:/samplewindow.qml")));
    }
    mainWindow->close();
    qObject->deleteLater();
}

/* main.qml */
import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    MouseArea {
        anchors.fill: parent
        onClicked: backend.changeWindow()
    }

    Text {
        text: qsTr("main window")
        anchors.centerIn: parent
    }
}

/* samplewindow.qml */
import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    MouseArea {
        anchors.fill: parent
        onClicked: backend.changeWindow()
    }

    Text {
        text: qsTr("sample window")
        anchors.centerIn: parent
    }
}

它在 QML 中非常容易......您不需要創建自己的 window 加載器,因為 QML 已經有加載器。 考慮這個樣本。 希望這對你有用。

主文件

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "backendcppclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    BackendCPPClass backendCPPClass; /// create instance of backend class.
    engine.rootContext()->setContextProperty("backend", &backendCPPClass); /// Set context propert so that we can access in QML.

    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();
}

main.qml

import QtQuick 2.14
import QtQuick.Window 2.14

Window {
    visible: true
    width: 640
    height: 480
    Loader {
        id: windowLoader
        anchors.fill: parent
        source: backend.bSettingMainWindow ? "qrc:/mainwindow.qml" : "qrc:/basic.qml"
    }
}

qml.qrc

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
        <file>basic.qml</file>
        <file>mainwindow.qml</file>
    </qresource>
</RCC>

后端cppclass.h

#ifndef BACKENDCPPCLASS_H
#define BACKENDCPPCLASS_H

#include <QObject>

class BackendCPPClass : public QObject
{
    Q_OBJECT
public:
    explicit BackendCPPClass(QObject *parent = nullptr) {};
    Q_PROPERTY(MEMBER bSettingMainWindow NOTIFY bSettingMainWindowChanged)

signals:
    void bSettingMainWindowChanged();

private:
    bool bSettingMainWindow = false;

};

#endif // BACKENDCPPCLASS_H

后端cppclass.cpp

#include "backendcppclass.h"

BackendCPPClass::BackendCPPClass(QObject *parent) : QObject(parent)
{
    /// update any logic to change the variable bSettingMainWindow.
    /// QML will automatically validate it.
    bSettingMainWindow = true;
    emit bSettingMainWindowChanged();
}

Basic.qml 和 mainwindow.qml 可以是您自定義的特定 qmls。

暫無
暫無

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

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