Russian Qt Forum
Март 29, 2024, 17:36
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Qt Quick
(Модератор:
navrocky
) >
Правильное удаление объектов из ++ модели ассоциированной со списком в QML
Страниц: [
1
]
2
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Правильное удаление объектов из ++ модели ассоциированной со списком в QML (Прочитано 7375 раз)
Vladimir
Крякер
Offline
Сообщений: 305
Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
:
Январь 23, 2020, 16:37 »
Доброго дня! Вопрос как правильно удалять данные из модели сделанной таким образом:
https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html
пример с QObjectList-based Model.
В плюсовой части есть список QList<QObject*> lstData; в который добавляется структура типа
Код:
class Data: public QObject
{
Q_OBJECT
Q_PROPERTY(...)
public:
Data() {}
~Data()
{
qDebug() << "~Data";
}
....
};
добавляется lstData.append(new Data());
после этого делается context->setContextProperty("M_Data", QVariant::fromValue(lstData));
в QML части:
Код:
ListView
{
id: idTableBody
anchors { fill: parent }
clip: true
model: M_Data
}
и все вроде ок, когда я редактирую/добавляю данные в модель, а потом делаю обновление как написано по ссылке context->setContextProperty("M_Data", QVariant::fromValue(lstData));
интересности начинаются, когда я пытаюсь удалить данные..
чтобы удалить одну строку делаю так
Код:
for(int i = 0; i < lstData.count(); ++i)
{
auto *data= dynamic_cast<Data*>(lstData[i]);
if(data)
{
if(data->getNumber() == delNumberData)
{
lstData.removeAt(i);
delNumberReason = -1;
return true;
}
}
}
для удаления всех строк вызываю просто lstData.clear() и это работает, НО.. я не вижу, чтобы вызывался деструктор объекта!
removeAt(); и clear() вроде как и не должны его вызывать.. ок, тогда я делаю
delete lstData.takeAt(i); для удаления одной строчки и qDeleteAll(lstData); и для удаления всего списка и при этом деструктор вызывается с....(внимание!) обязательным крашем программы!
и вот собственно как это разрулить счастье, кто отвечает за освобождение памяти.. и как это правильно сделать?
«
Последнее редактирование: Январь 23, 2020, 21:33 от Vladimir
»
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4725
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #1 :
Январь 23, 2020, 18:19 »
может дело в том, что деструктор не объявлен виртуальным?
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Vladimir
Крякер
Offline
Сообщений: 305
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #2 :
Январь 23, 2020, 19:09 »
Цитата: kambala от Январь 23, 2020, 18:19
может дело в том, что деструктор не объявлен виртуальным?
это улучшило ситуацию, т.е. теперь он крашит не стабильно каждый раз, но все же крашит через какое-то количество удалений
Записан
Vladimir
Крякер
Offline
Сообщений: 305
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #3 :
Январь 23, 2020, 21:17 »
Как-то странно.. виртуальный деструктор нужен в базовом классе, для корректного удаления производных классов через указатель на базовый. Базовым классом для моего класса Data является QObject, а у него деструктор виртуальный! Поэтому вроде как все должно работать было и без добавления virtual в мой класс Data.. или что-то я не так понимаю
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4725
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #4 :
Январь 23, 2020, 23:57 »
нет, все наследники должны объявлять свой деструктор виртуальным.
раз падает при удалении объекта, значит он точно удаляется дважды.
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Old
Джедай : наставник для всех
Offline
Сообщений: 4349
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #5 :
Январь 24, 2020, 07:29 »
Нельзя просто так взять и удалить данные в модели не уведомив при этом вьюшки.
Почитайте про:
void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
void QAbstractItemModel::endRemoveRows()
Тоже касается и добавления данных в модель:
void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
void QAbstractItemModel::endInsertRows()
Ну и про другие случаи не забывайте, смотрите beginXXX, endXXX.
Записан
ssoft
Программист
Offline
Сообщений: 574
Re: Правильное удаление объектов из ++ модели k
«
Ответ #6 :
Январь 24, 2020, 07:37 »
Цитата: kambala от Январь 23, 2020, 23:57
нет, все наследники должны объявлять свой деструктор виртуальным.
С чего бы это?
Цитата: Vladimir от Январь 23, 2020, 16:37
для удаления всех строк вызываю просто lstData.clear() и это работает, НО.. я не вижу, чтобы вызывался деструктор объекта!
Здесь удаляются не экземпляры объектов, а чистится массив указателей на них. Никакой деструктор вызван не будет.
Цитата: Vladimir от Январь 23, 2020, 16:37
delete lstData.takeAt(i); для удаления одной строчки и qDeleteAll(lstData); и для удаления всего списка и при этом деструктор вызывается с....(внимание!) обязательным крашем программы!
А здесь сначала удаляется один экземпляр объекта, а затем удаляются все экземпляры объектов массива, в том числе и уже удаленный. Ошибка попытки повторного удаления.
Используйте qDeleteAll(lstData), а уже затем lstData.clear() и будет счастье.
Ну и не забывайте про beginRemoveRows/endRemoveRows и beginResetModel/endResetModel.
«
Последнее редактирование: Январь 24, 2020, 07:39 от ssoft
»
Записан
Vladimir
Крякер
Offline
Сообщений: 305
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #7 :
Январь 24, 2020, 09:33 »
Цитата: Old от Январь 24, 2020, 07:29
Нельзя просто так взять и удалить данные в модели не уведомив при этом вьюшки.
Почитайте про:
void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
void QAbstractItemModel::endRemoveRows()
Тоже касается и добавления данных в модель:
void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
void QAbstractItemModel::endInsertRows()
Ну и про другие случаи не забывайте, смотрите beginXXX, endXXX.
про эти методы я знаю, но где их взять если я не наследуюсь от QAbstractItemModel? по ссылке из доки, которую я привел в первом сообщении я использую
QObjectList-based Model, основанную просто на QList<QObject*>. если есть такой способ, то должен быть и корректный способо удаления без begin/end методов.
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4349
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #8 :
Январь 24, 2020, 09:38 »
Тогда попробуйте вначале установить новый новый список, в котором уже нет удаленных строк и только после этого удалить сами объекте.
Записан
Vladimir
Крякер
Offline
Сообщений: 305
Re: Правильное удаление объектов из ++ модели k
«
Ответ #9 :
Январь 24, 2020, 09:39 »
Цитировать
Используйте qDeleteAll(lstData), а уже затем lstData.clear() и будет счастье.
Именно так и делаю, но счастье не приходит, когда я писал про "delete lstData.takeAt(i); для удаления одной строчки и qDeleteAll(lstData); для удаления всего" - это разные функции удаления. когда я удаляю все я делаю сначала qDeleteAll(lstData), а потом lstData.clear(). и он рандомно крашит с виртуальным конструктором, a без виртульного он крашит стабильно
Записан
Vladimir
Крякер
Offline
Сообщений: 305
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #10 :
Январь 24, 2020, 09:41 »
Цитата: Old от Январь 24, 2020, 09:38
Тогда попробуйте вначале установить новый новый список, в котором уже нет удаленных строк и только после этого удалить сами объекте.
т.е. в context->setContextProperty("M_Data", QVariant::fromValue(QList<QObject*>())); сначала установить пустой список, а потом уже чистить.. это идея, попробую
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4349
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #11 :
Январь 24, 2020, 09:45 »
Цитата: Vladimir от Январь 24, 2020, 09:41
т.е. в context->setContextProperty("M_Data", QVariant::fromValue(QList<QObject*>())); сначала установить пустой список, а потом уже чистить.. это идея, попробую
Не обязательно.
Перед удалением объекта из списка через removeAt, вызвать у него deleteLater, сделать removeAt и установить новый список.
Записан
Vladimir
Крякер
Offline
Сообщений: 305
Re: Правильное удаление объектов из ++ модели связанной со списком в QML [DONE]
«
Ответ #12 :
Январь 24, 2020, 11:05 »
Eeeee вроде заработало. Всем спасибо! Eще потестирую.. но выглядит вроде все логично! Финальный вариант такой:
удаление одного
Код:
for(int i = 0; i < lstData.count(); ++i)
{
auto *data= dynamic_cast<Data*>(lstData[i]);
if(data)
{
if(data->getNumber() == delNumber)
{
lstData[i]->deleteLater();
lstData.removeAt(i);
delNumber = -1;
context->setContextProperty("M_Data", QVariant::fromValue(lstData));
return true;
}
}
}
удаление всех
Код:
context->setContextProperty("M_Data", QVariant::fromValue(QList<QObject*>()));
qDeleteAll(lstData);
lstData.clear();
остался открытый теоретический вопрос нужен ли деструктор виртульным делать в дочернем классе. вроде и без него работает..
здесь его объявляют только в базовом классе
http://cpp-reference.ru/articles/virtual-destructor/
«
Последнее редактирование: Январь 24, 2020, 11:15 от Vladimir
»
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4349
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #13 :
Январь 24, 2020, 11:10 »
Цитата: Vladimir от Январь 24, 2020, 11:05
остался открытый теоретический вопрос нужен ли деструктор виртульным делать в дочернем классе. вроде и без него работает..
Не нужно, если он в базовом уже виртуальный, то будет виртуальным и во всех потомках.
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4725
Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML
«
Ответ #14 :
Январь 24, 2020, 11:26 »
Цитата: ssoft от Январь 24, 2020, 07:37
Цитата: kambala от Январь 23, 2020, 23:57
нет, все наследники должны объявлять свой деструктор виртуальным.
С чего бы это?
спасибо, и правда, не нужно. почему-то запомнил, что лучше везде объявлять как виртуальный.
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [
1
]
2
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...