QML QQmlPropertyList — содержит время жизни объекта и «правила памяти»

Мне трудно подтвердить правила владения объектом для элементов, вставленных в QQmlPropertyList, когда он настраивается как часть компонента QML, определенного в C ++ с

Q_CLASSINFO("DefaultProperty", "values")

DTech спросил что-то подобное в: QQmlListProperty — доступный для записи QList нарушает правила управления памятью QML?, но его беспокоили последствия удаления компонентов, определенных в QML. Меня больше беспокоит требования к жизненному циклу объектов, включенных в список в целом.

Теперь из того, что я понимаю:

  1. Если дети созданы и вставлены из QML, их родители
    автоматически устанавливается и объекты управляются QmlEngine. (родитель должен быть уже определен при добавлении)

  2. Если я вставлю что-то со стороны C ++, мне нужно управлять
    Сама жизнь. (родитель будет nullptr при добавлении)

Документы QT для предупреждения о «нарушении правил управления памятью QML». в http://doc.qt.io/qt-5/qqmllistproperty.html но я не могу найти ничего, что на самом деле излагает это ясно и кратко.

В настоящее время я реализовал обертку вокруг вектора, очень похожего на
http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html

Однако я добавил два правила:

  1. Добавление проверок, чтобы увидеть, имеет ли добавляемый объект nullptr родитель, и если это так, становится владельцем
  2. При снятии флажка, если какой-либо объект принадлежит текущему родительскому списку, выполняет «deleteLater» для объекта и устанавливает для его родителя значение nullptr

Я предполагаю, что, потому что мы устанавливаем родителя при добавлении объектов с nullptr родители, QT удалит объекты QObject принадлежит автоматически, когда родитель выходит из области видимости.

Есть ли еще правила что мне не хватает и нужно знать?

Код для моей реализации на всякий случай вышеупомянутого требует небольшого пояснения:

template <typename T>
class QmlListFacade {
private:
std::vector<T *> _storage;

static void append(QQmlListProperty<T> *list, T *newValue) {
// take ownership of the object if none are currently defined
auto obj = static_cast<QObject *>(newValue);
if( obj->parent() == nullptr) {
obj->setParent(list->object);
}
auto internalList = reinterpret_cast<QmlListFacade *>(list->data);
internalList->_storage.push_back(newValue);
}

static int count(QQmlListProperty<T> *list) {
return reinterpret_cast<QmlListFacade *>(list->data)->_storage.size();
}

static T *get(QQmlListProperty<T> *list, int index) {
return reinterpret_cast<QmlListFacade *>(list->data)->_storage[index];
}

static void clear(QQmlListProperty<T> *list) {
auto internalList = reinterpret_cast<QmlListFacade *>(list->data);
for( auto item :internalList->_storage){
// only delete if we are the owners.
auto obj = static_cast<QObject *>(item);
if( obj->parent() == list->object){
obj->setParent(nullptr);
obj->deleteLater();
}
}
return internalList->_storage.clear();
}

public:
QmlListFacade() = default;QQmlListProperty<T> values(QObject *parent) {
return QQmlListProperty<T>(parent, this, &QmlListFacade::append, &QmlListFacade::count, &QmlListFacade::get,
&QmlListFacade::clear);
}

};

0

Решение

С точки зрения того, кто обнаружил сомнительное управление временем жизни объектов QML и боролся с этим уже почти 3 года, в этом окне опыта я не встречал ни одного случая декларативно определенного дерева объектов, с которым неправильно обращались.

Проблемы связаны с объектами, которые создаются динамически, они, как правило, иногда удаляются независимо от того, есть ли у них родительский объект или сколько активных ссылок на них существует в коде. Если вы хотите, чтобы они не были удалены, дайте им явное право собственности на CPP.

Это предотвратит уничтожение этих объектов двигателем во время его использования. Объекты по-прежнему будут собираться после уничтожения их родителей, как это происходит в C ++ API.

Обратите внимание, что это предупреждение присутствует только в конструкторе, который принимает QList а не тот, который принимает в указатели функции управления. Так что, если что-нибудь, вы можете по крайней мере найти утешение в том, что вы не используете этот формат Я сделал много испытаний на обоих и не столкнулся с какими-либо функциональными различиями. Это предупреждение могло быть неуместным, плохо сформулированным и даже совершенно бессмысленным в дополнение к тому, что оно не содержало контекста того, что оно означает и каковы могут быть его последствия. Просто будьте внимательны при тестировании, чтобы выявить любые проблемы в младенчестве.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]