[英]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.