PDA

View Full Version : [Qt 4.1.3] Child widget not destroyed



Dusdan
23rd May 2006, 15:38
I have a problem with Qt 4.1.3.

I wrote a custom QWidget (say: widget1) that creates another QWidget (say widget2) in another window, but when widget1 is destroyed widget2 is not destroyed. WIth Qt 4.1.2 widget2 is destroyed.

Here is the code I wrote:



void CustomWidget1::someMethod()
{
widget2 = new CustomWidget2(this);
widget2->setWindowFlags(Qt::Window);
widget2->setAttribute(Qt::WA_DeleteOnClose);
}


I found there are some changes in Qt 4.1.3 regarding QWidget.
from changes-4.1.3:



- QWidget
Made sure that the application does not close if a widget with a
visible parent exists.
Fixed issue where scroll() would scroll child widgets in some cases.
Fixed painting issues when resizing very large child widgets.
Fixed a bug preventing setCursor() from working with platform-
dependent cursors.

wysota
23rd May 2006, 16:08
Could you provide a minimal compilable example which reproduces the problem?

Dusdan
23rd May 2006, 16:27
test.pro


TEMPLATE = app
TARGET = test
DEPENDPATH += .
INCLUDEPATH += .

# Input
HEADERS = test.h
SOURCES = test.cpp


test.h


#include <QPushButton>

class MyButton : public QPushButton
{
Q_OBJECT
public:
MyButton(QWidget *);

public slots:
void mySlot();
};


test.cpp


#include <QApplication>
#include <test.h>

MyButton::MyButton(QWidget *parent = NULL) : QPushButton(parent)
{
setText("Test");
connect(this, SIGNAL(clicked()), this, SLOT(mySlot()));
}

void MyButton::mySlot()
{
QWidget *w = new QWidget(this);
w->setWindowFlags(Qt::Window);
w->setAttribute(Qt::WA_DeleteOnClose);
w->show();
}

int main(int argc, char **argv)
{
QApplication a(argc, argv);
MyButton button;

button.show();

return a.exec();
}


run the program, click on the button and then close the main window: if you use Qt-4.1.2 the child window is closed, if you use Qt-4.1.3 it's not.

wysota
23rd May 2006, 17:07
Unfortunately I don't have 4.1.3 compiled yet, so I can't verify it today. Can someone else with Qt 4.1.3 confirm the problem? Does the same happen for non-qwidget based classes too?

jpn
23rd May 2006, 17:22
What if you set the Qt::WA_DeleteOnClose attribute for the button as well? Oh, and then you might also need to allocate the button on the heap so it won't get destructed twice (when closing and when going out of scope in main).

michael
23rd May 2006, 19:48
Unfortunately I don't have 4.1.3 compiled yet, so I can't verify it today. Can someone else with Qt 4.1.3 confirm the problem? Does the same happen for non-qwidget based classes too?

Well I compiled his program and it does act the way he says.

Dusdan
23rd May 2006, 19:54
Well I compiled his program and it does act the way he says.On which platform? From your profile I suppose you're running Windows.

I'm using Linux, so this bug/feature is cross-platform :D

michael
23rd May 2006, 20:01
On which platform? From your profile I suppose you're running Windows.

I'm using Linux, so this bug/feature is cross-platform :D


Apparantly as I compiled on WindowsXP machine.

Best thing I can up with off the top of my head is to create an event handler to catch the close event and close all of the open child windows. Not much of a suggestion but it should work.

Whatever the case the parent widget isn't getting deleted until the child window is closed.

Michael

wysota
23rd May 2006, 20:25
What if you get rid of deleteOnClose and instead delete the widget manually (or using the deleteLater() slot).

wysota
23rd May 2006, 20:29
Jacek just suggested this might not be a bug after all. You're not deleting the parent widget, just closing it.

Try this:


int main(int argc, char **argv)
{
QApplication a(argc, argv);
MyButton *button = new MyButton(0, Qt::WA_DeleteOnClose); // modify the constuctor to accept flags
button->show();
QPushButton fakeButton;
fakeButton.show(); // to prevent application from closing too soon
return a.exec();
}

michael
23rd May 2006, 21:03
[QUOTE=wysota]Jacek just suggested this might not be a bug after all. You're not deleting the parent widget, just closing it.
[quote]

That is true, but (if I remember correctly) in previous versions closing the parent widget closed the children as well. I could be wrong though.

On a different note, and something I find strange, is if you change the flag from Qt::Window to Qt:Sheet it works the way the thread starter hopes (or believes) that it should.

jpn
23rd May 2006, 21:19
#include <QtGui>

class MyButton: public QPushButton
{
Q_OBJECT

public:
MyButton(QWidget* parent = 0) : QPushButton("Test", parent)
{
connect(this, SIGNAL(clicked()), this, SLOT(mySlot()));
}

private slots:
void mySlot()
{
QWidget* widget = new QWidget(this, Qt::Window);
widget->setAttribute(Qt::WA_DeleteOnClose);
// From docs: "By default this attribute is set for all widgets except
// transient windows such as splash screens, tool windows, and popup menus."
// Clear Qt::WA_QuitOnClose attribute. (Notice the difference if you comment this line out..)
widget->setAttribute(Qt::WA_QuitOnClose, false);
widget->show();
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyButton* w = new MyButton;
w->show();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
return a.exec();
}

#include "main.moc"

michael
23rd May 2006, 21:47
Well, changing that flag resolved the issue. Works as suggested. Hopefully it fixes the threadstarters problem.

However, according to this http://doc.trolltech.com/4.1/qapplication.html#quitOnLastWindowClosed-prop that should only apply if the window has no parent. So does the Qt app deparent the window because the Qt:Window flag is set?

Michael

Dusdan
24th May 2006, 08:17
Thank you very much guys: this way it works both with Qt-4.1.2 and with Qt-4.1.3