Evgenii Legotckoi
Evgenii Legotckoi27 листопада 2015 р. 09:54

QML - Урок 018. Завантажувач в QML Qt – Робота з динамічними компонентами

Для організації динамічної зміни компонентів зручно використовувати компонент Loader, який входить у QML QtQuick і є контейнером для ваших компонентів у додатку, який допустимо необхідно періодично замінювати в інтерфейсі.

Якщо провести аналогію, наприклад, з розробкою на Java під Android, там є система фрагментів, які також можуть замінюватися в контейнері для них, слідуючи логіці програми, що розробляється. Допустимо, Ми клацаємо на кнопку і в певному контейнері у нас замінюється один фрагмент іншим, а якщо клацаємо на іншу кнопку, то з'являється третій фрагмент, який замінює другий фрагмент собою.

Тому зробимо додаток, який матиме 5 кнопок і натисканням кожної кнопки в Loader будуть змінюватися фрагменти.

Структура проекту для роботи з Loader

  • QmlLoader.pro - профайл проекту;
  • main.cpp - основний файл вихідних кодів програми;
  • main.qml - основний файл кодів qml;
  • Fragment1.qml - перший фрагмент для заміни в Loader;
  • Fragment2.qml - другий фрагмент;
  • Fragment3.qml - третій фрагмент.

main.cpp створюється за замовчуванням і не змінюється, тому його лістинг наводиться не буде, так само як і профайлу проекту.

main.qml

Установка компонентів Loader може здійснюватися декількома способами:

  1. Через властивість source - у цьому випадку компонентом є файл QML та його вміст обмежений областю видимості у плані взаємодії з іншими елементами у файлі main.qml;
  2. Через властивість sourceComponent - в даному випадку встановлюються об'єкти Component, які містяться у файлі main.qml та не обмежені областю видимості при взаємодії з іншими об'єктами у main.qml;
  3. Встановлення через метод setSource() - в даному випадку є можливість задати додаткові параметри для об'єкта, наприклад рівень непрозорості, але не забувайте ці параметри встановлювати заново, інакше вони зберігаються навіть при установці нового компонента.

У наведеному нижче коді є шар з п'ятьма кнопками, об'єктом Loader , який є прямокутним контейнером, в який будуть розміщуватися наші фрагменти. Робота з розташуванням його у вікні програми виконується так, ніби це об'єкт типу 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 та інші фрагменти

Код Fragment1.qml та інших фрагментів ідентичний крім того, що вони мають різний колір фону.

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
    }

}

Підсумок

Після того, як Ви скомпонуєте вище написаний код, у Вас вийде програма, яка буде виглядати так, як показано на наступному рисунку. Демонстрацію роботи програми Ви можете побачити у відеоуроці.

Відеоурок

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

S
  • 18 жовтня 2017 р. 09:11

Добрый день интересует такой вопрос. С помощью QML возможно ли создавать многооконные приложения? Есть ли аналоги MDI area? Гугл не помогает, в документации только однооконные приложения с регистрацией в main.cpp. Какая практика вообще существует использования qml в создании больших приложений (многооконных).

Evgenii Legotckoi
  • 18 жовтня 2017 р. 09:28

День добрый!!

В QML нет аналога MDI area, но можно сделать стандартный проект на QWidget, добавить в главное окно QMdiArea, а в него добавлять QML-ки в качестве виджетов через QQuickWidget. Вот статья для примера, как отобразить виджет с QML в проекте на QWidget .

 
То есть получается некий костыль. В принципе, можно сделать и собственную MDIArea для QML, теоретически... это не должно составить труда. Но нужно подумать. Там по идее, нужно лишь сделать возможности для обработки изменения размера объектов, которые будут представлять из себя эти самые окна. А также реализовать логику перетаскивания окон и скроллинга для этой MDI area.
 
Просто многооконные приложение можно без проблем создавать на QML, вопрос лишь в том, насколько удачно можно реализовать некоторые сложные структуры интерфейса наподобие древовидных списков и этой самой MDI area.
S
  • 18 жовтня 2017 р. 09:37

Вот и я тоже пришел к такому же выводу, стандартное QWidget как обертка для QuickWidget-ов. А вообще практика применения QML для десктопов видимо такая же, я не нашел информации на этот счет вообще .

Evgenii Legotckoi
  • 18 жовтня 2017 р. 09:43

Я не встречался с повсеместным использованием QML для десктопа, если приложение также не затачивается на работу под мобильные платформы. Видимо, поэтому и MDI area до сих пор не существует для QML, поскольку имеет крайне низкий приоритет.

t
  • 01 листопада 2019 р. 11:28
  • (відредаговано)

Добрый день! Благодарю за хороший пример, только его бы дополнить немного: что если мне нужно из фрагментов "Fragment 1.qml" - "Fragment 2.qml" посылать сигналы, причём набор сигналов разный. Как это лучше организовать, какие тут есть варианты?

P.S. Сам спросил - сам отвечаю: :)

    Loader
    {
        onLoaded: {
            if(item.objectName == "Fragment1") { // Set object name to an item beforehand
                item.mySignal1.connect(targetObject.function1);
                item.mySignal2.connect(targetObject.function2);
            }
        }
    }

Another variant: move above logic inside

Fragment1.qml
and call these functions via property like this:

    property var LoaderParent: parent.parent
    ...
    onMySignal1:{
        LoaderParent.function1(params);
    }
Evgenii Legotckoi
  • 04 листопада 2019 р. 06:16

Добрый день. Не успел Вам ответить ))
Для ответа на ваш вопрос, по моему мнению лучше было бы объединить всю информациб о сигналах и слотах, которая присутсвует на сайте.
Поэтому я первоначально потратил время на подготовку статьи, касательно вашего вопроса.
Можете прочитать здесь QML - Урок 036. Работа с сигналами и слотами в QML .
Надеюсь, что найдёте ещё что-нибудь дополнительное для себя.

t
  • 04 листопада 2019 р. 09:34

Благодарю!

T
  • 05 лютого 2021 р. 04:21

Всем привет. А есть ли возможность динамически загрузить qml файл, который скачивается во время работы программы и помещается в определённую папку на диске C?

Evgenii Legotckoi
  • 02 липня 2021 р. 07:39

Да можно, нужно указать относительный путь к qml файлу

КФ
  • 19 липня 2021 р. 01:31

добрый день, грамотно ли использовать loader для загрузки небольших диалоговых окон по клику из меню? и если да, то возникает проблема: загрузили первое диалоговое окно, потом его закрыли, а открыть снова получается только после згразки другого д.о. Проблема в свойтве status?

Лично для меня loader - это компонень, который загружает какую-то часть внутри окна, поэтому с этой точки зрения я бы не стал рассматривать использование loader лоя открытия окон, только для заполнения этих окон контентом.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
Дмитрий

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:60бали,
  • Рейтинг балів-1
Дмитрий

C++ - Тест 003. Условия и циклы

  • Результат:92бали,
  • Рейтинг балів8
d
  • dsfs
  • 26 квітня 2024 р. 04:56

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
Останні коментарі
k
kmssr08 лютого 2024 р. 18:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 01:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 10:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 08:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 грудня 2023 р. 21:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
G
George1307 травня 2024 р. 00:27
добавить qlineseries в функции в функции: "GPlotter::addSeries(QString title, QVector &arr)" я вызываю метод setChart(...), я в конструктор передал адрес на QChartView элемент
BlinCT
BlinCT05 травня 2024 р. 05:46
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
PS
Peter Son03 травня 2024 р. 17:57
Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
Evgenii Legotckoi
Evgenii Legotckoi02 травня 2024 р. 14:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderChe30 квітня 2024 р. 04:22
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

Слідкуйте за нами в соціальних мережах