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
AD

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

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 01:37

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

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 01:29

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

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 06:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 03:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 09:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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