Unsolved Children QWidgets always on top of parent
-
Hi !
I got a main window (QMainWindow) with some children (QWidget). Those children widgets are set with the Qt::Window flag (so they stand by themselves on the desktop). However, when the main window gets the focus (e.g. by clicking on it on the desktop), all children stay on top of the main window.
I would like the main window to appear in front of its children when it gets the focus. I tried different window flags setup but none of them worked.
-
Hi, and welcome
What flags did u use on the children?
you can try raise() on mainwindow but if u used
Qt::WindowStaysOnTopHint on children, it might now work. -
I use the following piece of code to detach children widgets from the mainwindow.
widget->setWindowFlags( Qt::Window ); widget->setAttribute( Qt::WA_DeleteOnClose ); widget->show();
I also tried to use the "raise" method on the mainwindow but the children don't let their parent move to the foreground.
-
Instead of overriding child behavior one by one (window flag and deletion policy) how about not making it a child in the first place?
-
The main window holds the application data and the children widgets operate on these data. The lifetime of the application data and the lifetime of the children widgets are both handled by the main window. By doing this, it is not possible to have a widget pointing to the application data before it has been created or after it has been destroyed since both share the same lifetime.
However, it seems the parent/child mechanism is responsible for the memory management AND the windows z-ordering.
-
Same problem,
QWidget *w = new QWidget(this); w->setWindowFlags(Qt::Window); w->setAttribute(Qt::WA_DeleteOnClose); w->show();
any advice?
-
Same advice: how about not making it a child?
-
@Tom.C-Dev said:
The main window holds the application data and the children widgets operate on these data. The lifetime of the application data and the lifetime of the children widgets are both handled by the main window.
same problem.
-
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.