Реклама

QML - Урок 007. ListView Qml. Динамическое создание и удаление элементов

Android, ListItem, ListModel, ListView, QML, Qt

В статье про динамическое создание виджетов в Qt я уже рассказывал, как создавать и удалять кнопки динамически, а также как с ними взаимодействовать. И там использовался Vertical Layout , а случае с Qml мы сможем использовать ListView Qml, как аналогично используется при программирование в Java под Android. Что, к слову говоря, также применимо при программировании на Qt под Android.

В статье про динамическое создание виджетов использовались для примера объекты класса QButton. В данной статье будут использоваться объекты Button Qml, о кастомизации которых было рассказано в следующей статье . Но кнопки будут размещаться в ListView Qml.

Структура проекта для работы с ListView Qml

На это раз обойдёмся проектом, созданным по умолчанию и даже без дизайнера интерфейсов. Тем более, что на момент написания статьи не все параметры можно было задать в дизайнере. А структура проекта следующая:

  • QmlDynamic.pro - профайл проекта;
  • deployment.pri - файл правил деплоя на целевую платформу;
  • main.cpp - основной файл запуска приложения;
  • main.qml - qml файл с исходными кодами программы

main.qml

Поскольку все остальные файлы не представляют для нас никакого интереса и создаются по умолчанию, то сразу перейдём к разбору полётов с файлом main.qml.

Алгоритм работы программы следующий. В верхней части окна приложения имеется объект Row, в котором располагается текстовое поле и две кнопки. Остальную часть окна приложения занимает объект ListView Qml. По нажатию одной из кнопок в Row создаётся динамический объект в ListView Qml, который содержит кнопку. По нажатию динамической кнопки в текстовое поле в Row передаётся индекс ListElement, в котором находится кнопку, по которой производилось нажатие. И далее нажатием второй кнопки в объекте Row по индексу из текстового поля удаляется элемент из ListView Qml, а значение в текстовом поле стирается.

Примечателен тот факт, что при удалении элемента, который располагается в середине списка, например, индексы всех элементов, следующих за этим элементом уменьшаются на один. То есть индексы элементов пересчитываются автоматически.

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    /* Номер создаваемой кнопки, для её визуальной идентификации
     * при демонстрации проекта
     */
    property int number: 0

    /* Строка с полем, где отображается индекс нажатой динамической кнопки,
     * кнопкой для создания динамических кнопок,
     * и кнопкой для удаления динамических кнопок по индексу
     * */
    Row {
        id: row
        // Задаём размеры строки и прибиваем к верхней части окна приложения
        height: 50
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right

        // Задаём размещение поля с индексом кнопки
        Rectangle {
            width: (parent.width / 5)
            height: 50

            // Устанавливаем текстовое поле для размещения индекса кнопки
            Text {
                id: textIndex
                anchors.fill: parent
                text: ""
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }

        // Кнопка для создания динамических кнопок
        Button {
            id: button1
            text: qsTr("Create Button")
            width: (parent.width / 5)*2
            height: 50

            /* По клику по кнопке добавляем в model ListView
             * объект, с заданными параметрами
             * */
            onClicked: {
                listModel.append({idshnik: "Button " + (++number)})

            }
        }

        // Кнопка для удаления динамических кнопок
        Button {
            id: button2
            text: qsTr("Delete Button")
            width: (parent.width / 5)*2
            height: 50

            // Удаляем кнопку по её индексу в ListView
            onClicked: {
                if(textIndex.text != ""){
                    listModel.remove(textIndex.text)
                    textIndex.text = "" // Обнуляем текстовое поле с индексом
                }
            }
        }
    }

    // ListView для представления данных в виде списка
    ListView {
        id: listView1
        // Размещаем его в оставшейся части окна приложения
        anchors.top: row.bottom
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.right: parent.right

        /* в данном свойстве задаём вёрстку одного объекта
         * который будем отображать в списке в качестве одного элемента списка
         * */
        delegate: Item {
            id: item
            anchors.left: parent.left
            anchors.right: parent.right
            height: 40

            // В данном элементе будет находиться одна кнопка
            Button {
                anchors.fill: parent
                anchors.margins: 5

                /* самое интересное в данном объекте
                 * задаём свойству text переменную, по имени которой будем задавать
                 * свойства элемента
                 * */
                text: idshnik

                // По клику по кнопке отдаём в текстовое поле индекс элемента в ListView
                onClicked: {
                    textIndex.text = index
                }
            }
        }

        // Сама модель, в которой будут содержаться все элементы
        model: ListModel {
            id: listModel // задаём ей id для обращения
        }
    }
}

Итог

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

Видеоурок

Реклама

Комментарии

Здравствуйте,


Скажите, как реализовать следующее. Из объекта C++ посылается сигнал. Этот сигнал передает int ID - номер элемента.  В QML этот сигнал принимается и объект из ListModel с index == ID, например, меняет текст или свой  цвет.

Не хотелось бы повторяться. В статье по сигналам и слотам в QML есть вариант использования C++ объекта. Там используется тип Connections , который можно настроить на сигнал, который передаёт некое значение, тот же самый ID.

Connections {
    target: appCore 
    onSendToQml: {
        
    }
}
При этом сигнатура сигнала и обработчика не прописывается в этом соединении. Мы просто знаем, что в сигнале передаётся ID типа int, например с таким названием: sendedID.

Далее необходимо по этому ID изменить цвет. Тут есть такой момент, Изменения в свойствах делегата ListView необходимо делать через модель данных. То есть, модель данных должна содержать поле с указанием цвета. Можно сделать по умолчанию чёрный, а потом изменять его.
delegate: Text {
    anchors.left: parent.left
     anchors.right: parent.right
     height: 50
    horizontalAlignment: Text.AlignHCenter
    verticalAlignment: Text.AlignVCenter

    color: textColor // Роль с цветом
    text: textList // Роль с текстом
}
Тогда изменение цвета будет выглядеть так:
Connections {
    target: appCore 
    onSendToQml: {
          listModel.get(sendedID).textColor = "blue"
    }
}

Большое спасибо за ответ.

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
  • BlinCT
  • 22 октября 2017 г. 12:46

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

  • Результат 64 баллов
  • Очки рейтинга -1
  • Kiops
  • 22 октября 2017 г. 3:56

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

  • Результат 86 баллов
  • Очки рейтинга 6
  • Kiops
  • 22 октября 2017 г. 2:41

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

  • Результат 100 баллов
  • Очки рейтинга 10
Последние комментарии
  • EVILEG
  • 21 октября 2017 г. 3:06

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

Добавил архив с проектом

  • EVILEG
  • 20 октября 2017 г. 20:06

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

После работы поищу, должен где-то быть на винте.

  • Миша
  • 20 октября 2017 г. 20:04

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

не могли бы вы выложить архив с рабочей версией скрипта?

  • EVILEG
  • 20 октября 2017 г. 20:03

Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками

Использование дизайнера в Qt Creator и использование ui файлов является распространённой практикой в Qt фреймворке. Написать отдельную статью про то, что это такое? - может быть. Опи...

  • Миша
  • 20 октября 2017 г. 19:43

Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками

Но почему вы это не описали? Не могли бы вы описать.

Сейчас обсуждают на форуме
  • EVILEG
  • 22 октября 2017 г. 12:05

Закрепление якорей в момент создания объекта через JS

Добрый день! Якоря - это не те свойства, которые можно устанавливать сразу по инициализации, лучше их править после создания объекта, поскольку при одновременной установке они могут в...

  • EVILEG
  • 21 октября 2017 г. 23:33

Создание истории редактирования постов на сайте

Ясно. Тогда я лучше не буду тратить время на его проверку. Тем более, что я использую гугловский prettyprint для подсветки кода. Спасибо за информацию.

QFile::copy() возвращает false

Получилось! Спасибо огромное! path1 = "C:/Users/555/Pictures/00GAF13AP001-002.jpg"true

  • cordsac
  • 19 октября 2017 г. 15:49

How can I select the QGraphicView Item and change the properties

Ok I'll check it sir,If you can please do article(tutorial) about this,Its really useful.Thank you if you can give me some sample code when you free.thanks again

  • cordsac
  • 17 октября 2017 г. 19:28

How can I open SVG file through QT

Okay,Thank you sir :)