Консультация № 176905
25.02.2010, 12:06
43.34 руб.
0 7 1
Здравствуйте, уважаемые эксперты!
Пишу программу с использованием Qt 4.4.0 в связке с g++ 4.1.
Задача: функция получает в качестве параметра содержание некоей книги в виде списка строк (QStringList) и отображает этот список в объекте класса QTreeWidget. Необходимо, чтобы виджет очищался при каждом новом вызове функции, т.е. чтобы каждый раз отображалось содержание новой книги, а не добавлялось к предыдущему (как реально происходит):



Элементы объекта QTreeWidget (QTreeWidget* pContentsWidget;) хранятся в списке QList<QTreeWidgetItem*> ContentsItems;
Попытки очищать список элементов и сам виджет перед вставкой нового содержания ни к чему не привели:

Код:

void TNavigationWidget::SetNewContents(QStringList sContents)
{
ContentsItems.clear(); // Очищаем старый список
pContentsWidget->clear(); // Удаляем старые элементы

for(int i = 0; i < sContents.size(); ++i) // Добавляем новое содержание
{
QStringList sString;
sString << sContents[i];
ContentsItems.append(new QTreeWidgetItem((QTreeWidget*)0, sString));
}
pContentsWidget->insertTopLevelItems(0, ContentsItems);
}


Пытался проходить по элементам в цикле (включая виджеты QTreeWidget, отвечающие за отображение QTreeWidgetItem*) с тем же результатом:

Код:

void TNavigationWidget::SetNewContents(QStringList sContents)
{
for(int i = 0; i < pContentsWidget->topLevelItemCount(); ++i)
{
pContentsWidget->removeItemWidget(ContentsItems[i], 0);
}

while(!ContentsItems.isEmpty()) delete ContentsItems.takeFirst();

for(int i = 0; i < sContents.size(); ++i)
{
QStringList sString;
sString << sContents[i];
ContentsItems.append(new QTreeWidgetItem((QTreeWidget*)0, sString));
}
pContentsWidget->insertTopLevelItems(0, ContentsItems);
}


Вопрос: как очистить QTreeWidget от старых элементов?

Обсуждение

давно
Академик
20764
1861
25.02.2010, 12:30
общий
25.02.2010, 16:36
это ответ
Здравствуйте, Dr_Andrew.

void QTreeWidget::clear ()
Это slot, поэтому в документации в списке методов он упомянут в другом месте.
Список указателей очищать, естественно, бесполезно. Этот список вообще бесполезен - items всегда можно извлечь из самого QTreeWidget.
Доступ к items можно осуществлять либо через topLevelItem(index) либо извлечь invisibleRootItem() и уже через его child(index), что удобно для "настоящих" деревьев. Я изначально создаю TreeWidgetItem(parent,...), а не добавляю его потом.
5
Спасибо за ценные замечания, которые позволили оптимизировать код!
давно
Старший Модератор
17042
808
25.02.2010, 12:48
общий
Хватов Сергей:
Обратите внимание: в коде №1 вопроса виджет pContentsWidget (QTreeWidget) очищается именно этим методом, clear:

Код:

pContentsWidget->clear();


Вот только это не приводит ни к каким видимым результатам.

Цитата: Хватов Сергей

Список указателей очищать, естественно, бесполезно. Этот список вообще бесполезен


Ну я использую его для того, чтобы заполнить QTreeWidget. А Вы какой вариант предложите?
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
давно
Академик
20764
1861
25.02.2010, 13:13
общий
Dr_Andrew:
Вот это странно. Я достаточно широко использую QTreeWidget (правда в последнее время на python), и clear() работал всегда послушно
А доступ к items можно осуществлять либо через topLevelItem(index) либо извлечь invisibleRootItem() и уже через его child(index), что удобно для "настоящих" деревьев
давно
Старший Модератор
17042
808
25.02.2010, 13:13
общий
Хватов Сергей:
Вы правы, действительно, список QList<QTreeWidgetItem*> ContentsItems; бесполезен (забавно, но именно вариант со списком был в примере по использованию QTreeWidget, идущий в составе Qt). Упростил код следующим образом:

Код:

void TNavigationWidget::SetNewContents(QStringList sContents)
{
pContentsWidget->clear();

for(int i = 0; i < sContents.size(); ++i)
{
QStringList sString;
sString << sContents[i];
pContentsWidget->insertTopLevelItem(i, new QTreeWidgetItem(sString));
}
}


Но и в этом варианте результат всё тот же (см. скриншот в вопросе).
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
давно
Академик
20764
1861
25.02.2010, 13:21
общий
увидел различие: я изначально создаю TreeWidgetItem(parent,...), а не добавляю его потом. Может, из-за этого?
давно
Старший Модератор
17042
808
25.02.2010, 13:23
общий
Хватов Сергей:
Да мне и самому странно, т.к. документация по Qt настаивает, что для очистки QTreeWidget следует использовать слот clear(). По совету уважаемого ged попробовал удалять перебором:

Код:

void TNavigationWidget::SetNewContents(QStringList sContents)
{
for(int i = 0; i < pContentsWidget->topLevelItemCount(); ++i)
{
pContentsWidget->removeItemWidget(pContentsWidget->topLevelItem(i), 0);
}

for(int i = 0; i < sContents.size(); ++i)
{
QStringList sString;
sString << sContents[i];
pContentsWidget->insertTopLevelItem(i, new QTreeWidgetItem(sString));
}
}



Но - увы! - результат всё тот же. Ладно, доберусь до дома попробую откомпилировать из-под Linux: Windows-версии Qt иногда выкидывают странные штуки...
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
давно
Старший Модератор
17042
808
25.02.2010, 16:33
общий
Хватов Сергей:
Большое спасибо, всё работает! Ошибка была в передаваемом параметре функции: как-то позабыл, что для каждой книги нужно создавать новое DOM-дерево... Всё вылечилось строчками

Код:

delete pBook;
pBook = new TFBDomTree(this);


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

Код:

void TNavigationWidget::SetNewContents(QStringList sContents)
{
pContentsWidget->clear();

for(int i = 0; i < sContents.size(); ++i)
{
QTreeWidgetItem* pTreeWidgetItem = new QTreeWidgetItem(pContentsWidget);
pTreeWidgetItem->setText(0, sContents[i]);
pContentsWidget->insertTopLevelItem(i, pTreeWidgetItem);
}
}
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
Форма ответа