Evgenii Legotckoi
Evgenii LegotckoiҚар. 27, 2015, 9: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, 9:11 Т.Ж.

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

Evgenii Legotckoi
  • Қаз. 18, 2017, 9:28 Т.Ж.

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

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

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

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

Evgenii Legotckoi
  • Қаз. 18, 2017, 9:43 Т.Ж.

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

t
  • Қар. 1, 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
  • Қар. 4, 2019, 6:16 Т.Ж.

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

t
  • Қар. 4, 2019, 9:34 Т.Ж.

Благодарю!

T
  • Ақп. 5, 2021, 4:21 Т.Ж.

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

Evgenii Legotckoi
  • Шілде 2, 2021, 7:39 Т.Ж.

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

КФ
  • Шілде 19, 2021, 1:31 Т.Ж.

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

Evgenii Legotckoi
  • Шілде 20, 2021, 4:30 Т.Ж.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз