Proper way to open a QDialog
-
Hello! I'm trying to figure out a way to properly open a QDialog immediately after QMainWindow is shown. In examples below
class WMain : public QMainWindow ... class WNew : public QDialog
So far I've tried three approaches:
1)void WMain::showEvent(QShowEvent *event) { QMainWindow::showEvent(event); WNew window(this); window.exec(); }
QMainWindow is not shown before QDialog is shown. Internet says it's because QDialog::exec is a synchronous call. Changing showEvent to the first paintEvent doesn't solve the problem (QMainWindow is shown before QDialog is shown, but some QMainWindow controls may be black). Using timer-based solutions doesn't look right.
2)void WMain::showEvent(QShowEvent *event) { QMainWindow::showEvent(event); WNew window(this); window.open(); }
QDialog is not shown at all. I assume it's because QDialog::open is an asynchronous call and WNew destructor is called when code exits showEvent function.
3)void WMain::showEvent(QShowEvent *event) { QMainWindow::showEvent(event); WNew *window = new WNew(this); window->open(); }
This seems to work, but there is a memory leak. WNew destructor is not called when the dialog is closed. Can you suggest please where I should call the destructor? Or some different approach?
-
Hi,
Can you explain your use case ?
As for the memory leak, you can set the ”WA_DeleteOnClose” widget attribute.
-
My use case is that I have a dialog for creating a new document. This dialog should be initiated by a user click and also opened on application start.
WA_DeleteOnClose worked for me. Thank you. I would have never guessed this attribute.It's particularly convenient that I can programmatically control when to use it. (Use it when dialog object is created in heap and don't use it when dialog object is created in stack)
// on application start void WMain::showEvent(QShowEvent *event) { QMainWindow::showEvent(event); WNew *window = new WNew(this); window->setAttribute(Qt::WA_DeleteOnClose); window->open(); } // on user click void WMain::on_actionNew_triggered() { WNew window(this); window.exec(); }
-
The you should rather use a single shot QTimer with 0 as timeout value at the end of your constructor to call a slot that will show your dialog. This way the event loop will have started properly and your WMain object should be visible.
-
SGaist, yes this approach is even better. It solved problem with dialog centering (alignment relative to parent) and initial dialog 'active' status. I wouldn't come up with '0' argument in a lifetime. I thought about very small numbers but not '0'. :) I guess '0' works because (if I recall) timer events are processed in event loop only when there are no other events (in win32 at least).
void WMain::showEvent(QShowEvent *event) { QMainWindow::showEvent(event); QTimer::singleShot(0, [this]() { WNew window(this); window.exec(); }); }