Russian Qt Forum
Ноябрь 23, 2024, 22:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Удаление объектов. Рекурсия  (Прочитано 6512 раз)
Ovoshlook
Гость
« : Май 31, 2011, 11:39 »

Возможно не в том разделе но все же.
Существует компановшик, на который кладутся еще компановщики, и в них так же кладутся компановшики, и так далее сколько угодно.

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

Пытаюсь сделать это следующим образом:

1. Функция для удаления виджетов из компановщика
Код:
void OTS_MainWindow::DeleteAllWidgets(QLayout *layout)
 {

     QLayoutItem *item;
     while ((item=layout->takeAt(0)) !=0)
     {
         QWidget  *w = item->widget();
         delete item;

         layout->removeWidget(w);
         delete w;
     }

 }

2. Функция для удаления компоновщика и виджетов лежащих на нем
Код:
void OTS_MainWindow::DeleteAllLayouts(QLayout *layout)
{
     if (layout->count()==0) DeleteAllWidgets(layout);
     else
         {
            int size=layout->count();
            while (size!=0)
            {
                QLayout *SubLayout=static_cast<QLayout*>(layout->itemAt(size-1));
                DeleteAllLayouts(SubLayout);
                --size;
            }
         }
}

Проблема в том что последняя функция рушит программу, причем рушит только тогда когда пытается удалить компоновщики, если же их нет то функция отрабатывает обсалютно нормально. то есть до else все происходит хорошо.

Не совсем понятно где может быть проблема так как логика вполне прозрачна мне кажется. Собственно в этом и вопрос.

Заранее спасибо за помощь и терпение.
« Последнее редактирование: Май 31, 2011, 11:41 от Ovoshlook » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Май 31, 2011, 11:46 »

в DeleteAllWidgets() наверное правильно будет так:
Код
C++ (Qt)
QWidget  *w = item->widget();
layout->removeWidget(w);
delete w;
delete item;
Записан

Изучением 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
Ovoshlook
Гость
« Ответ #2 : Май 31, 2011, 11:51 »

Ну собственно здесь не принципиально) Хотя по логике конечно правильнее. Но собственно проблемы это так или иначе не решит к сожалению((
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Май 31, 2011, 12:15 »

По смыслу это вручную делаться не должно - просто создать виджет на верхнем/нужном уровне (который будет парентом всего хозяйства) - и его когда надо просто delete
Записан
Ovoshlook
Гость
« Ответ #4 : Май 31, 2011, 15:59 »

привязывать к парент не всегда удобно... а функция для удаления нужна((
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Май 31, 2011, 16:19 »

привязывать к парент не всегда удобно... а функция для удаления нужна((
Тебе может и неудобно, только Qt это сделает в любом случае.
Т.е. достаточно удалить либо сам лейаут либо его элементы ( qDeleteAll( QObjectList( layout()->children() ) ).
« Последнее редактирование: Май 31, 2011, 16:25 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Ovoshlook
Гость
« Ответ #6 : Май 31, 2011, 16:32 »

В том то и дело что если удалить компановщик виджеты останутся лежать. По крайней мере в это теме http://www.prog.org.ru/topic_10935_0.html было так. ДА и сам я тоже на это натыкался.

Вы только не подумайте что я сомневаюсь в ваших словах. Уже проверять пытаюсь ваш способ))



К сожалению ваш метод не удалил виджеты. Хотя лайоуты были удалены все. По крайней мере дебаг показал так

qDeleteAll(QObjectList(layout->children()));
qDebug()<<layout->count();

вывод:0.

получается что виджеты потом непонятно куда падают, потому что метод  DeleteAllWidgets(layout)ж в данном случае убрать их не может...

(сам метод рабочий 100% потому что его я использовал в других моментах удачно.)


« Последнее редактирование: Май 31, 2011, 16:50 от Ovoshlook » Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #7 : Май 31, 2011, 17:01 »

Сорри, беру свои слова обратно.
Чего-то перемудрил Грустный

Цитировать
получается что виджеты потом непонятно куда падают, потому что метод  DeleteAllWidgets(layout)ж в данном случае убрать их не может...
Виджеты становятся потомками виджета, на котором был лейаут и удалять уже нужно детей этого виджета.
Вот работающий пример:
Код
C++ (Qt)
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QTest>
 
int main( int argc, char** argv )
{
QApplication app( argc, argv );
QWidget w;
 
while( 1 )
{
QTest::qWait( 500 );
QGridLayout* l = new QGridLayout;
 
for( int i = 0; i < 10; i++ )
for( int j = 0; j < 10; j++ )
l->addWidget( new QPushButton( QString( "%1:%2" ).arg( i ).arg( j ) ),
i, j );
w.setLayout( l );
 
if( !w.isVisible() )
w.show();
 
QTest::qWait( 500 );
qDeleteAll( w.children() );
}
 
return 0;
}
 

Т.е. моё утверждение насчёт
Цитировать
Тебе может и неудобно, только Qt это сделает в любом случае.
верно.
« Последнее редактирование: Май 31, 2011, 17:21 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Ovoshlook
Гость
« Ответ #8 : Июнь 01, 2011, 15:49 »

Спасибо за пример!)

но у меня к сожалению при удалении таким образом происходит крах:
и так
 qDeleteAll(TabWidget->currentWidget()->children());
и так
 qDeleteAll(QObjectList(TabWidget->currentWidget()->children()));
Вот с таким списком сообщений:
warning: can't find linker symbol for virtual table for `QMetaObject::._19' value
warning: can't find linker symbol for virtual table for `QMetaObject::._19' value
warning: can't find linker symbol for virtual table for `QMetaObject::._87' value
warning:   found `typeinfo for QEventLoop' instead
warning: can't find linker symbol for virtual table for `QMetaObject::._19' value
warning: can't find linker symbol for virtual table for `QMetaObject::._19' value
warning:   found `typeinfo for QWhatsThat' instead
warning: can't find linker symbol for virtual table for `QMetaObject::<anonymous struct>' value
warning:   found `typeinfo for QDialog' instead
Записан
Ovoshlook
Гость
« Ответ #9 : Июнь 02, 2011, 17:09 »

Всем спасибо за советы. проблему решил следующим образом:
Удалил основной виджет на котором все лежит.

Только в моем случае получилось что из пушки по воробъям потому, что пришлось удалять аж целый Tab и потом его заново пересоздавать для того чтобы создать виджет лежащий на табе.

Правда сначала я попробывал немного подругому сделать:

Структура таба была изначально такая
Tabwidget->Layout(основной компоновщик для виджета)->itemAt(компоновщики, которые я накидывал на основной, в них так же были еще компоновщики и виджеты которые мне нужно было удалить)

У меня получалось удалить все компоновщики до Tabwidget->Layout, но при этом виджеты не удалялись.

Тогда я решил сделать вот что:
На основной компановщик я клал еще один виджет:
Tabwidget->Layout-Widget
На него лепил основной компоновщик
Tabwidget->Layout-Widget-Layout
И потом уже клал то что мне нужно
Tabwidget->Layout-Widget-Layout-ItemAt(i)

Только либо путь был слишком большой либо где то промахнулся но при таком раскладе прога вылетала с крахом.
Так как время поджимает пришлось стрелять из пушки по воробьям.

Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #10 : Июнь 02, 2011, 17:46 »

Ну не знаю что там у тебя делается, но вот это работает:
Код
C++ (Qt)
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QTabWidget>
#include <QTest>
 
int main( int argc, char** argv )
{
QApplication app( argc, argv );
QTabWidget tw;
QWidget w;
bool not_shown = true;
 
tw.addTab( &w, "Tab" );
 
while( 1 )
{
tw.setTabText( 0, QString( "Tab (%1 children )" ).arg( w.children().count() ) );
 
QTest::qWait( 500 );
 
QGridLayout* l = new QGridLayout( &w );
 
for( int i = 0; i < 5; i++ )
for( int j = 0; j < 5; j++ )
l->addWidget( new QPushButton( QString( "%1:%2" ).arg( i ).arg( j ) ),
i, j );
 
tw.setTabText( 0, QString( "Tab (%1 children )" ).arg( w.children().count() ) );
 
if( not_shown )
{
not_shown = false;
tw.show();
}
 
QTest::qWait( 1000 );
 
qDeleteAll( w.children() );
 
if( tw.isHidden() )
break;
}
 
return 0;
}
 
Записан

Qt 5.11/4.8.7 (X11/Win)
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.222 секунд. Запросов: 23.