Um einen dynamischen Wechsel von Komponenten zu organisieren, ist es praktisch, die Komponente Loader zu verwenden, die in QML QtQuick enthalten ist und ein Container für Ihre Komponenten in der Anwendung ist, die beispielsweise benötigt werden regelmäßig in der Schnittstelle ersetzt.
Wenn wir beispielsweise eine Analogie zur Entwicklung in Java für Android ziehen, dann gibt es ein System von Fragmenten, die auch im Container für sie ersetzt werden können, der Logik der zu entwickelnden Anwendung folgend . Angenommen, wir klicken auf eine Schaltfläche und ersetzen in einem bestimmten Container ein Fragment durch ein anderes, und wenn wir auf eine andere Schaltfläche klicken, erscheint ein drittes Fragment, das das zweite Fragment durch sich selbst ersetzt.
Daher erstellen wir eine Anwendung mit 5 Schaltflächen, und durch Drücken jeder Schaltfläche im Loader ändern sich die Fragmente.
Projektstruktur für die Arbeit mit Loader
- QmlLoader.pro - Projektprofil;
- main.cpp - Quelldatei der Hauptanwendung;
- main.qml - Haupt-QML-Codedatei;
- Fragment1.qml - erstes Fragment, das im Loader ersetzt werden soll;
- Fragment2.qml - zweites Fragment;
- Fragment3.qml ist das dritte Fragment.
main.cpp wird standardmäßig erstellt und nicht geändert, daher wird es nicht aufgelistet, ebenso wenig wie das Projektprofil.
main.qml
Die Installation von Komponenten in Loader kann auf verschiedene Arten erfolgen:
- Durch die source -Eigenschaft – in diesem Fall ist die Komponente eine QML -Datei und ihr Inhalt ist in Bezug auf die Interaktion mit anderen Elementen in der main.qml-Datei beschränkt;**
- Über die Eigenschaft sourceComponent - in diesem Fall werden die Component-Objekte gesetzt, die in der Datei main.qml enthalten sind und bei der Interaktion mit anderen Objekten in main nicht durch den Geltungsbereich eingeschränkt sind .qml;
- Installation über die Methode setSource() - in diesem Fall ist es möglich, zusätzliche Parameter für das Objekt zu setzen, z. B. die Deckkraft, aber vergessen Sie nicht, diese Parameter zurückzusetzen, da sie sonst gespeichert werden auch bei der Installation einer neuen Komponente.
Im folgenden Code gibt es eine Ebene mit fünf Schaltflächen, ein Loader -Objekt, bei dem es sich um einen rechteckigen Container handelt, in dem unsere Fragmente platziert werden. Seine Position im Anwendungsfenster wird behandelt, als wäre es ein Objekt vom Typ Rectangle .
import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.1 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") // Слой с кнопками, которые будут менять фрагменты RowLayout { id: rowLayout anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.margins: 5 Button { text: qsTr("Фрагмент 1") // Загрузка компонента из файла onClicked: loader.source = "Fragment1.qml" } Button { text: qsTr("Фрагмент 2") // Загрузка компонента через метод setSource с установкой параметров фрагмента onClicked: loader.setSource("Fragment2.qml", {"opactity": 1 }) } Button { text: qsTr("Фрагмент 3") // Загрузка компонента через метод setSource с установкой параметров фрагмента onClicked: loader.setSource("Fragment3.qml", {"opacity": 0.5}) } Button { text: qsTr("Фрагмент 4") // Установка фрагмента из объекта Component onClicked: loader.sourceComponent = fragment4 } Button { text: qsTr("Фрагмент 5") // Установка фрагмента из объекта Component onClicked: loader.sourceComponent = fragment5 } } // Loader для загрузки фрагментов Loader { id: loader anchors.top: rowLayout.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.topMargin: 5 source: "Fragment1.qml" } // Четвёртый фрагмент в качестве компонета Component { id: fragment4 Rectangle { anchors.fill: parent color: "blue" Text { text: "Fragment 5" color: "white" anchors.top: parent.top anchors.right: parent.right anchors.margins: 50 font.pixelSize: 30 renderType: Text.NativeRendering } } } // Пятый фргамент в качестве компонента Component { id: fragment5 Rectangle { anchors.fill: parent color: "black" Text { text: "Fragment 5" color: "white" anchors.top: parent.top anchors.right: parent.right anchors.margins: 50 font.pixelSize: 30 renderType: Text.NativeRendering } } } }
Fragment1.qml und andere Fragmente
Der Code für Fragment1.qml und die restlichen Fragmente ist identisch, außer dass sie alle eine andere Hintergrundfarbe haben.
import QtQuick 2.5 Rectangle { anchors.fill: parent color: "green" Text { text: "Fragment 1" color: "white" anchors.top: parent.top anchors.right: parent.right anchors.margins: 50 font.pixelSize: 30 renderType: Text.NativeRendering } }
Insgesamt
Nachdem Sie den obigen Code zusammengestellt haben, haben Sie eine Anwendung, die wie die in der folgenden Abbildung gezeigte aussieht. Sie können eine Demonstration der Anwendung im Video-Tutorial sehen.
Добрый день интересует такой вопрос. С помощью QML возможно ли создавать многооконные приложения? Есть ли аналоги MDI area? Гугл не помогает, в документации только однооконные приложения с регистрацией в main.cpp. Какая практика вообще существует использования qml в создании больших приложений (многооконных).
День добрый!!
В QML нет аналога MDI area, но можно сделать стандартный проект на QWidget, добавить в главное окно QMdiArea, а в него добавлять QML-ки в качестве виджетов через QQuickWidget. Вот статья для примера, как отобразить виджет с QML в проекте на QWidget .
Вот и я тоже пришел к такому же выводу, стандартное QWidget как обертка для QuickWidget-ов. А вообще практика применения QML для десктопов видимо такая же, я не нашел информации на этот счет вообще .
Я не встречался с повсеместным использованием QML для десктопа, если приложение также не затачивается на работу под мобильные платформы. Видимо, поэтому и MDI area до сих пор не существует для QML, поскольку имеет крайне низкий приоритет.
Добрый день! Благодарю за хороший пример, только его бы дополнить немного: что если мне нужно из фрагментов "Fragment 1.qml" - "Fragment 2.qml" посылать сигналы, причём набор сигналов разный. Как это лучше организовать, какие тут есть варианты?
P.S. Сам спросил - сам отвечаю: :)
Another variant: move above logic inside
and call these functions via property like this:Добрый день. Не успел Вам ответить ))
Для ответа на ваш вопрос, по моему мнению лучше было бы объединить всю информациб о сигналах и слотах, которая присутсвует на сайте.
Поэтому я первоначально потратил время на подготовку статьи, касательно вашего вопроса.
Можете прочитать здесь QML - Урок 036. Работа с сигналами и слотами в QML .
Надеюсь, что найдёте ещё что-нибудь дополнительное для себя.
Благодарю!
Всем привет. А есть ли возможность динамически загрузить qml файл, который скачивается во время работы программы и помещается в определённую папку на диске C?
Да можно, нужно указать относительный путь к qml файлу
добрый день, грамотно ли использовать loader для загрузки небольших диалоговых окон по клику из меню? и если да, то возникает проблема: загрузили первое диалоговое окно, потом его закрыли, а открыть снова получается только после згразки другого д.о. Проблема в свойтве status?
Лично для меня loader - это компонень, который загружает какую-то часть внутри окна, поэтому с этой точки зрения я бы не стал рассматривать использование loader лоя открытия окон, только для заполнения этих окон контентом.