Unsolved Children QWidgets always on top of parent
-
So just delete the window when the data is destroyed. If you want the window to go away when mainwindow is destroyed you can link them like this:
QWidget *w = new QWidget(); w->show(); connect(this, &QMainWindow::destroyed, w, &QWidget::deleteLater);
-
Ok, thanks for reply.
-
@Chris-Kawa said:
QWidget *w = new QWidget();
w->show();
connect(this, &QMainWindow::destroyed, w, &QWidget::deleteLater);doesn't work, after close main window widget stays.
Any ideas why? -
doesn't work
It works fine. Just not as you think it does.
By default the application event loop exits when last top level window is closed ( see quitOnLastWindowClosed property).The main window is destroyed only after the event loop quits (as the
main
function scope ends). But the event loop does not quit since there's another top level window. You can force the main winodw to be destroyed when it closes, but then you can't put it on the stack.Here's a complete example:
int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow* mainWindow = new QMainWindow(); mainWindow->setAttribute(Qt::WA_DeleteOnClose); QWidget* otherWidget = new QWidget(); QObject::connect(mainWindow, &QMainWindow::destroyed, otherWidget, &QWidget::deleteLater); mainWindow->show(); otherWidget->show(); return a.exec(); }
-
@Chris-Kawa said:
The main window is destroyed only after the event loop quits (as the main function scope ends). But the event loop does not quit since there's another top level window. You can force the main winodw to be destroyed when it closes, but then you can't put it on the stack.
Sorry for interjecting, couldn't one call the
close
slot on all the child widgets and still use the stack? I mean, instead of subscribing to thedestroyed
signal, possibly something like this?class Controller : public QObject { Q_OBJECT signals: void closing(); protected: virtual bool eventFilter(QObject * watched, QEvent * event) { if (event->type() == QEvent::Close) emit closing(); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Controller ctrl; QMainWindow mainWindow; mainWindow.installEventFilter(&ctrl); QWidget otherWidget; QObject::connect(&ctrl, SIGNAL(closing()), &otherWidget, SLOT(close())); mainWindow.show(); otherWidget.show(); return QApplication::exec(); }
-
@kshegunov Yup, would work too. Personally I try to trim classes when possible. Creating a specialized one when the same can be done in a one time 2 lines of connects/attribute settings seems too "Javish" to me :P
You would also need a separate header/cpp for the Controller cause you can't put Q_OBJECT in a .cpp file. Not worth the effort IMO.But yeah, both solutions work fine and the choice is a matter of preference as to where to put responsibilities.
-
@Chris-Kawa said:
Creating a specialized one when the same can be done in a one time 2 lines of connects/attribute settings seems too "Javish" to me :P
Right, I agree in principle, however I'd make two points:
- Usually people derive from
QMainWindow
and use it as a controller, then the whole creating a separate class will not be needed, as an override ofcloseEvent
is going to be sufficient. - Ordinarily, I'd have a controller class to initialize my forms anyway (I tend not to derive from the widget classes), so in this case my proposal could also work.
In any case, I'm just putting it as an option. ;)
- Usually people derive from
-
Thanks for solutions, but seems "doesn't work" for me.
As I understand "Child" widgets always in main and create with QMainWindow, but i need something like:
MainWindow->button->clicked->tcpsocket(getSomeData)->MainWindow->readData->createWidgetWithSomeData. -
@Xardas
Maybe there's a misunderstanding, no one said that creating the widgets inmain()
is the only way. You can create them anywhere in the code. I believe Chris' suggestion is your best bet. As an example:class MainWindow : public QMainWindow { Q_OBJECT // ... some more code signals: void closed(); private slots: void showDataWidget(QByteArray); protected: virtual void closeEvent(QCloseEvent *); }; void MainWindow::showDataWidget(QByteArray data) { // Create the widget QWidget * dataWidget = new QWidget(); //< NO PARENT! dataWidget->setAttribute(Qt::WA_DeleteOnClose); //< Closing the window will free the memory // ... Fill up the widget's data ... QObject::connect(this, SIGNAL(closed()), dataWidget, SLOT(deleteLater())); //< Connect the clean up routine } void MainWindow::closeEvent(QCloseEvent * event) { emit closed(); QMainWindow::closeEvent(event); }
This should be easy to adapt to your case.
Kind regards.
-
@kshegunov
Yes, misunderstanding. Thanks, work perfectly.