Как динамически уничтожать / удалять компонент QML?

#qt #qml

#qt #qml

Вопрос:

Я пытаюсь динамически создавать, а затем уничтожать компонент на основе взаимодействия пользователя с флажком в QML. Установите флажок «Создать компонент». Снимите флажок, уничтожьте компонент. Создание компонента работает, но его уничтожение — нет. Компонент все еще там.

В документации в QT docs здесь упоминается, что метод destroy должен работать после создания компонента. Есть идеи, что я могу здесь делать неправильно? Приведенный ниже код.

 import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1

Rectangle {
    property var deficiencyType
    width: 600
    height: 800
    color:"white"
    CheckBox {
        id:checkbox
        text: "Check deficiency on/off"
        onClicked: {
            if (checked) {
                deficiencyType = Qt.createComponent("Form.qml")
                deficiencyType.createObject(columnRef)
            } else {
                deficiencyType.destroy()
                console.log(deficiencyType)
            }
        }
    }
    ColumnLayout {
        id:columnRef
        Layout.fillHeight: true
        Layout.fillWidth: true
        anchors {
            top: checkbox.bottom
            topMargin: 10
        }
    }
}
  

Ответ №1:

Для этого случая вы могли бы использовать загрузчик, например :

 import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1

Rectangle {
    width: 600
    height: 800
    color:"white"

    CheckBox {
        id: checkBox

        text: "Check deficiency on/off"
    }

    ColumnLayout {
        Layout.fillHeight: true
        Layout.fillWidth: true

        anchors {
            top: checkbox.bottom
            topMargin: 10
        }

        Loader {
            id: formLoader

            active: checkBox.checked
            source: "Form.qml"
        }
    }
}
  

Существует несколько способов обработки динамических компонентов QML. Вы также должны проверить эти :

Редактировать:

Чтобы обрабатывать динамическое создание нескольких элементов из определенной модели, вы должны использовать повторитель, подобный этому :

 import QtQuick 2.7
import QtQuick.Layouts 2.14
import QtQuick.Controls 2.14

Rectangle {
    width: 600
    height: 900
    color:"white"

    property ListModel forms: ListModel {
        ListElement {
            formName: "Form one"
            formSource: "Form1.qml"
        }

        ListElement {
            formName: "Form two"
            formSource: "Form2.qml"
        }

        ListElement {
            formName: "Form three"
            formSource: "Form3.qml"
        }
    }

    RowLayout {
        anchors.fill: parent

        Repeater {
            model: forms

            delegate: Item {
                CheckBox {
                    id: checkBox

                    text: "Check "   modelData.formName   " on/off"
                }

                ColumnLayout {
                    Layout.fillHeight: true
                    Layout.fillWidth: true

                    anchors {
                        top: checkbox.bottom
                        topMargin: 10
                    }

                    Loader {
                        active: checkBox.checked
                        source: modelData.formSource
                    }
                }
            }
        }
    }
}
  

Комментарии:

1. Я согласен, что большую часть времени Qt.createComponent/ CreateObject не нужен. Чем меньше императивного кода, тем лучше. Чтобы быть еще более декларативным, вы могли бы просто привязать свойство Loader active checked к свойству CheckBox и избавиться от обработчика onClicked сигналов.

2. Спасибо за пример загрузчика. Это определенно сработало бы для примера, который я привел выше. Но я не упомянул, что у меня есть 10 разных флажков, которые генерируют 10 разных форм, возможно, одновременно. Итак, мне нужно установить несколько источников для источника загрузчика. Вот почему я сначала не преследовал Loader. Я могу создать 10 разных загрузчиков, но является ли это лучшей практикой здесь?

3. Вы должны использовать повторитель для динамического создания нескольких разных элементов QML. Посмотрите на model свойство, которое позволяет вам предоставлять модель списка данных.

Ответ №2:

Как сказал @Alaenix, вместо вас может работать загрузчик. Но, чтобы прямо ответить на ваш вопрос, проблема с вашим destroy() заключается в том, что вы уничтожаете компонент, а не созданный вами объект. Итак, меняем этот код:

                     deficiencyType = Qt.createComponent("Form.qml")
                    deficiencyType.createObject(columnRef)
  

к этому:

                     var component = Qt.createComponent("Form.qml")
                    deficiencyType = component.createObject(columnRef)
  

должно решить вашу проблему.

Комментарии:

1. Хотя использование загрузчиков может быть лучшей практикой, как сказал @Alaenix, этот ответ решает проблему, с которой я столкнулся. Я не упоминал, что мне приходилось генерировать несколько форм, поэтому для настройки загрузчиков потребуется больше времени. Но это отлично работает для меня.