Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] закрытие всех дочерних форм


Автор: chesterfielda 13.7.2009, 18:54
Доброго времени суток!!!
Я еще совсем новичок в Qt, поэтому прошу помощи smile ....
У меня такая проблема:
Есть три класса с формами:С1,С2 и С3. Из С1 посредством слота вызывается С2, а из С2 также по слоту вызывается С3
Все эти классы создаются динамически, т.е. С1 *с=new C1(parent); c->show();
И вот я хочу чтобы при закрытии самого основного первого класса С1, закрывались все дочерние существующие классы....для этого  я в конструкторе класса С1 задаю: 
this->setAttribute(Qt::WA_DeleteOnClose);
все вроде получается, все закрывается, только вот память не освобождается....видимо, потому что у меня в деструкторе ничего не прописано....А что там прописать точно и не знаю  smile 
Вот пример:
класс С1
Код

С1::С1(QWidget *parent)
    : QMainWindow(parent){
ui.setupUi(this);
auct=new QSqlQueryModel(0);
str="SELECT auction.id,Method_razm.Name,auction.Num_izv,Format(auction.Date_auct,'dd.mm.yyyy') "
        "FROM auction INNER JOIN Method_razm ON auction.rf_methodID=Method_razm.id";
auct->setQuery(str,db);
ui.tableView->setModel(auct);
ui.tableView->hideColumn(0);
connect(ui.tableView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(lpu()));
this->setAttribute(Qt::WA_DeleteOnClose);
}
C1::~C1()
{
}
void C1::lpu(){ //слот
    int auctid;
    sel=ui.tableView->selectionModel();
    index=sel->currentIndex();
    auctid=auct->data(auct->index(index.row(),0)).toInt();
    с= new С2(this,auctid);
    с->show();
    
}

класс С2
Код

С2::С2(QWidget *parent,int auctID)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    zakazch=new QSqlQueryModel(0);
    str="SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN from "
               "zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
               "where zakazchik.rf_auctID="+auctID+"";
    zakazch->setQuery(str);
    ui.tableLPU->setModel(zakazch);
    connect(ui.tableLPU,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(zakaz()));
}
С2::~С2()
{
}
void С2::zakaz(){ слот 
    int zakazchid;
    sel=ui.tableLPU->selectionModel();
    index=sel->currentIndex();
    zakazchid=zakazch->data(zakazch->index(index.row(),0)).toInt();
    z=new C3(this,zakazchid);
    z->show();
}

класс С3 аналогичный

Автор: SABROG 13.7.2009, 19:16
Цитата(chesterfielda @  13.7.2009,  18:54 Найти цитируемый пост)
все вроде получается, все закрывается, только вот память не освобождается

Как ты об этом узнаешь?

Автор: chesterfielda 13.7.2009, 19:38
В процессах приложение остается....
И не компилится, типо приложение открыто

Автор: ufna 13.7.2009, 23:11
ну дак все правильно. Смотри сам - дочерние виджеты вызваны динамические, класс-родитель имеет только указатель на них. При удалении объекта этого класса при закрытии окна - удаляются указатели, а не сами объекты. Тут несколько вариантов:
1. лови QCloseEvent
2. сделай деструктор, где будешь убивать эти объекты.

Автор: chesterfielda 14.7.2009, 07:21
Вот и я думаю, что нужно так сделать...только вот не знаю как правильно, вот смотрите:
Если я в деструкторе класса C1 напишу delete c;, то это не правильно т.к. если не будет вызван слот lpu(), то и не будет создана эта вторая форма и выскакивает соответственно ошибка ((( т.е. нужно определить был ли с создан сначало....
или в классе С2 в деструкторе написать delete this;, только вот не знаю на сколько это корректно , или даже если только в деструкторе С1 напишу delete this, то тоже все работает, правда не понимаю почему, я ведь удаляю только текущий объект
Подскажите пожалуйста новичку как лучше сделать, чтобы потом глюков не было
Да, и еще...а если я напишу не delete c;, с->close() это не одно и тоже будет??

Автор: SABROG 14.7.2009, 08:14
При удалении (delete) C1  все дочерние окна должны удаляться автоматически, если их родитель C1. При аттрибуте WA_DeleteOnClose, если закрывать C1 через крестик, то должно удалиться и C1 окно и все его дети. Когда все окна будут удалены/закрыты должен произойти выход программы, т.е. флаг QuitOnLastWindowClosed стоит по-умолчанию. Если этого не происходит, значит где-то косяк.

Автор: chesterfielda 14.7.2009, 08:47
Значит,если в главном классе С1 установлен атрибут WA_DeleteOnClose,то дочтаточно только в деструкторе этого класса написать delete this, а в деструкторах дочерних классов ничего не удалять???

Автор: chesterfielda 14.7.2009, 09:20
Или вообще ничего удалять не нужно, если установлен Qt::WA_DeleteOnClose????Поидее же этот атрибут означает, что при закрытии все должно удалится...

Автор: ufna 14.7.2009, 10:06
кинь в личку исходники, гляну в чем там дело.

c->close() и delete© - асбсолютно разные вещи. Первое- функция, которая много что внутри делает, а второе - непосредственное прямое удаление объекта класса, это уже к С++ напрямую.

Этот атрибут говорит о том, что при закрытии окна происходит еще и его удаление, ничего в деструктор насчет самого этого окна добавлять не нужно, оно удаляется средствами Qt.

Автор: chesterfielda 14.7.2009, 11:37
ufna, я вам отправила...

Автор: ufna 14.7.2009, 11:58
пока ничего не получил  smile 

Автор: chesterfielda 14.7.2009, 12:46
ufna,я вам еще разочек отправила...
После многочисленных экспериментов вот что получается:
1.Если в деструкторе вторго класса, который вызывается из первого написать какое-нибудь сообщение , наприер QMessageBox::information(0,"деструктор","класса С2");
то приложение удаляется из процессов
2.Если в деструкторе первого класса,из которго вызывается второй написать 
if(c->isVisible()) c->close();, то тоже все удаляется из процессов
2-е конечно понятно, а вот по-поводу 1-го вообще не понимаю :(( И как лучше сделать тогда 

Автор: SABROG 14.7.2009, 13:06
Напиши минимальный пример, который можно будет собрать на любой машине и прикрепи к посту.

Автор: chesterfielda 14.7.2009, 13:29
Выкладываю самый простенький пример....
Не ругайте сильно, если ошибка элементарная smile 

Автор: SABROG 14.7.2009, 13:39
У меня в процессах ничего не остается, программа завершается корректно (Qt 4.5.2). Возможно проблема в версии Qt.

Автор: chesterfielda 14.7.2009, 14:09
т.е. когда открыты две формы, а вы закрываете только первую у Вас все корректно работает???
У меня версия 4.3.3

Автор: ufna 14.7.2009, 14:21
да, пример собирается и отлично работает, т.е. закрывается как надо.


Попробуй полностью пересобрать проект. Кстати, какую версию Qt и какой компилятор/IDE используешь?

Автор: chesterfielda 14.7.2009, 14:37
Версия Qt 4.3.3, а компилятор MinGW...
Вот блин, почему же так...у меня в моей проге тоже самое и вот простенькую сделала-тоже самое, поэтому пересборка сдеся не поможет...
Все окошки закрываются, а экзешник остается в процессах..И что самое странное,если в деструкторе дочернего класса doch, раскомментировать вывод сообщения, то псле закрытия главного окна выводится это сообщение и закрывается дочернее окно и из процессо экзешник удаляется...вот почему интересно так??

Автор: ufna 14.7.2009, 15:19
загрузи весь код сюда в форум, мне так ничего и не пришло пока что. И перекомпилировать все-таки попробуй smile

Автор: chesterfielda 14.7.2009, 15:34
В моем приложении абсолютно таже проблема, только кода больше...

Автор: ufna 14.7.2009, 15:46
Может стоит обновить версию заодно?

Тут путь самый простой такой - очищать все наделанные компилятором файлы, и компилить сначала. Ошибка скорее всго не в коде, а в настройках.

Автор: chesterfielda 14.7.2009, 16:25
ну неужели все от версии зависит... smile 
Вот сейчас дома пересобрала,выложенный сдесь пример - таже проблема...
Давайте я вам свой экзешник выложу и вы посмотрите....

Автор: SABROG 14.7.2009, 16:31
Ты и Evgeniya одно и то же лицо?

Запустил .exe'шник со своими библиотеками Qt проблем не наблюдается. Значит дело в Qt, которые ты используешь.

Автор: chesterfielda 14.7.2009, 16:34
ну да...  smile 

Автор: ufna 14.7.2009, 16:43
Цитата(SABROG @ 14.7.2009,  16:31)
Запустил .exe'шник со своими библиотеками Qt проблем не наблюдается. Значит дело в Qt, которые ты используешь.

то же самое. 

Автор: chesterfielda 14.7.2009, 16:50
А если я в деструкторе класса main_form пишу:
Код

main_form::~main_form()
{
delete this;
}

то все работает....уж не знаю на сколько это правильно

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)