crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Странное поведение QTreeWidgetItem::removeChild
chereppiter
  опции профиля:
сообщение 18.12.2012, 10:56
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 30
Регистрация: 12.11.2012
Пользователь №: 3595

Спасибо сказали: 0 раз(а)




Репутация:   0  


Есть функция построения дерева (QTreeWidget), в которой для каждого элемента верхнего уровня рекурсивно вызывается функция добавления отпрысков:

void addChilds(QTreeWidgetItem* item, int id)
{
QTreeWidgetItem* child;
for (unsigned int i = 0; i < nodes.size(); ++i)
{
if (nodes[i].parentid == id)
{
child = new QTreeWidgetItem(item);
child->setText(0, QString::fromUtf8(nodes[i].name.c_str()));
addChilds(child, nodes[i].id);
if (!child->childCount())
{
item->removeChild(child);
delete child;
}
}

}
}

По возвращению из рекурсивной addChilds, если у текущего чаилда детей нет, то он удаляется. Ситуация такая: на одной из итераций цикла к item был добавлен child (и не был удалён, т.к. у него тоже есть дети). На одной из последующих итераций создаётся child, для которого потом childCount оказывается 0, поэтому он удаляется (item->removeChild(child)). При этом почему-то вместе с этим отпрыском удаляется и тот, который был добавлен на одной из предыдущих итераций. Проблема решается исключением из вышеприведённого кода строчки:

item->removeChild(child);

Т.е. если удаление выглядит так:

if (!child->childCount())
{
delete child;
}

, то всё работает нормально.
Кто-нибудь знает причину этого загадочного явления?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
chereppiter
  опции профиля:
сообщение 19.12.2012, 11:00
Сообщение #2


Студент
*

Группа: Участник
Сообщений: 30
Регистрация: 12.11.2012
Пользователь №: 3595

Спасибо сказали: 0 раз(а)




Репутация:   0  


1) Чтобы было более понятно, приведу полный текст функций, строящих дерево:

void SelCameraDialog::buildTree()
{
tree->clear();
for (unsigned int i = 0; i < nodes.size(); ++i)
{
if (nodes[i].parentid == 0)
{
QTreeWidgetItem* item = new QTreeWidgetItem(tree);
item->setText(0, QString::fromUtf8(nodes[i].name.c_str()));
addChilds(item, nodes[i].id);
if (!item->childCount()) delete item;
}
}
}


void SelCameraDialog::addChilds(QTreeWidgetItem* item, int id)
{
QTreeWidgetItem* child;
for (unsigned int i = 0; i < nodes.size(); ++i)
{
if (nodes[i].parentid == id)
{
child = new QTreeWidgetItem(item);
child->setText(0, QString::fromUtf8(nodes[i].name.c_str()));
addChilds(child, nodes[i].id);
if (!child->childCount()) delete child;

}

}
for (unsigned int i = 0; i < cameras.size(); ++i)
{
if (cameras[i]->nodeid == id)
{
QString camName = QString::fromUtf8(cameras[i]->name.c_str());
QString camId = QString::number(cameras[i]->id);
child = new QTreeWidgetItem(item);
child->setText(1, camId);
child->setText(0, camName);
child->setText(2, (cameras[i]->allowOnline ? "+" : "-"));
child->setText(3, (cameras[i]->allowArchive ? "+" : "-"));
child->setText(4, (cameras[i]->ptz ? "+" : "-"));
child->setTextAlignment(2, Qt::AlignCenter);
child->setTextAlignment(3, Qt::AlignCenter);
child->setTextAlignment(4, Qt::AlignCenter);

}

}

}

В buildTree в дерево добавляются корневые узлы, не имеющие родителя (т.е. у которых parentid==0). Далее вызывается метод addChilds(item, id) для рекурсивного добавления дочерних элементов к узлу item. id в теле item нету, т.к. item содержит только название узла. У узла может быть 2 типа дочерних элементов: другой узел или камера. И то, и то - по сути просто структуры, имеющие в качестве основных полей идентификатор (id), идентификатор родительского узла (parentid) и название (name). Отличие только в том, что узел может иметь детей, а камера - нет.

2) nodes - это стандартный вектор структур:
struct NodeParams
{
int id;
std::string name;
int parentid;

};

Заполняется заранее инфой, распарсенной из xml-ки.
cameras - аналогичный вектор.

3) Ребёнка в любом случае приходится сначала создать, чтобы было к чему подцеплять потомков, если таковые есть. Соответственно, если потомков нет, его приходится удалять. К дереву его, конечно, можно подцеплять только в том случае, если потомки есть, но это в данном случае не принципиально.
На самом деле интересен сам факт такого странного поведения removeChild. Что вообще по идее делает этот метод? Мне кажется, что он должен просто удалять указатель на объект QTreeWidgetItem из списка дочерних элементов. А тут получается, что я создал 2 разных объекта QTreeWidgetItem, прицепил указатели на них к родительскому QTreeWidgetItem, потом вызовом removeChild удалил указатель на один из них из списка дочерних элементов родительского QTreeWidgetItem, после чего этот список оказался пуст, хотя должен был содержать 1 элемент. Выглядит как-то нелогично :)

Выше приведённый код работает правильно, неправильно работал такой фрагмент addChilds:

if (nodes[i].parentid == id)
{
child = new QTreeWidgetItem(item);
child->setText(0, QString::fromUtf8(nodes[i].name.c_str()));
addChilds(child, nodes[i].id);
if (!child->childCount())
{
item->removeChild(child);
delete child;

}

}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме
- chereppiter   Странное поведение QTreeWidgetItem::removeChild   18.12.2012, 10:56
- - Алексей1153   в поставленном вопросе много неизвестного: 1) чем ...   18.12.2012, 23:54
- - chereppiter   1) Чтобы было более понятно, приведу полный текст ...   19.12.2012, 11:00
- - Алексей1153   chereppiter, что делает этот метод, можно прочитат...   19.12.2012, 14:37
- - chereppiter   Не понимаю, в чём неправильность моего подхода к д...   19.12.2012, 17:55
- - Алексей1153   chereppiter, тогда прикрепи проект (удали лишнее),...   20.12.2012, 6:56
- - chereppiter   Создал отдельный маленький тестовый проект. Глючна...   20.12.2012, 15:53
- - Алексей1153   в общем, вскрытие показало, что чукча умер от вскр...   21.12.2012, 0:25
- - iReset   Насколько я понял при беглом просмотре исходников,...   21.12.2012, 9:13
- - Алексей1153   iReset, вообще, забавная ситуация - указываем конк...   21.12.2012, 11:10
|- - iReset   Цитата(Алексей1153 @ 21.12.2012, 12:10) i...   21.12.2012, 12:30
- - chereppiter   Ну вот, совместными усилиями докопались до истины....   21.12.2012, 11:26


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.11.2024, 10:34