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:

    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.

    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.

    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?


  • Lifetime Qt Champion

    Hi,

    Can you explain your use case ?

    As for the memory leak, you can set the ”WA_DeleteOnClose” widget attribute.



  • You can use show() :

    void show()
            {
            QMainWindow::show();
            WNew dlg(this);
            dlg.exec();
            }
    


  • 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();
    }
    

  • Lifetime Qt Champion

    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();
        });
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.