Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

How to close a widget that has no parent from another widget?



  • I have a widget I'll call the "top" widget that creates a QUndoView widget. I'm able to display and use the QUndoView widget with no problem but am unable to close it when the application exits. I could solve this by making the top widget the parent but this messes up my top widget display. What I did instead was in the top widget header I add the variable

    @QUndoView *m_undoView;@

    Then in the top widget cpp I added the code
    @m_undoView = new QUndoView(stack);@

    where stack is the pointer to my undo stack (QUndoStack * stack). I can remove the m_undoView widget by simply using
    @delete m_undoView;
    m_undoView=0;@

    but this doesn't work if this code is placed in the top widget destructor. I found an old post at
    "http://www.qtforum.org/article/21347/solved-qdialog-not-closed-when-qmainwindow-closed.html":http://www.qtforum.org/article/21347/solved-qdialog-not-closed-when-qmainwindow-closed.html which seemed to indicate that I may be able to use the closeEvent to get around this problem. I tried that but it didn't work.

    The problem is that no matter what I try the QUndoView widget remains visible and active when I close the application (unless the top widget closes it prior the application closing). The top widget is closed successfully as its parent is the main window but since the QUndoView widget has no parent it not only remains open it causes error messages to be generated.

    The question is how can I close the QUndoView widget when the application exits?



  • It doesn't work in the destructor of the main window because the main window object, assuming the typical creation of this on the stack, is not destroyed until after the event loop exits. The event loop will not exit while another top-level window is open.

    If you have a pointer to the other window then calling otherWidget->close() in your main window's closeEvent() should do it (unless the other widget cancels its close in its own closeEvent()). This, for example, works:

    @
    #include <QApplication>
    #include <QWidget>
    #include <QCloseEvent>
    #include <QDebug>

    class MainWidget: public QWidget {
    Q_OBJECT
    public:
    MainWidget(QWidget *p = 0): QWidget(p) {
    otherWidget = new QWidget;
    otherWidget->setWindowTitle("Other");
    otherWidget->show();
    }

    ~MainWidget() {
        qDebug() << Q_FUNC_INFO;
        delete otherWidget;
    }
    

    protected:
    void closeEvent(QCloseEvent *event) {
    qDebug() << Q_FUNC_INFO;
    otherWidget->close();
    event->accept();
    }

    private:
    QWidget *otherWidget;
    };

    int main(int argc, char **argv) {
    QApplication app(argc, argv);
    MainWidget m;
    m.show();
    return app.exec();
    }
    #include "main.moc"
    @



  • ChisW67:
    Thanks for the information. My situation is somewhat more complicated than your example but your example and explanation gave me the clue I needed to solve my problem. In essence my "top" widget is a descendant of the main window so in order to close the QUndoView window I had to create a chain of getters from my top widget to my main window that passed the pointer to the QUndoView widget back to the main window. Then using that pointer I could use the close function to close the QUndoView window.

    I also set

    @m_viewUndo->setAttribute(Qt::WA_DeleteOnClose,true);@

    when m_viewUndo was created. I don't know if this is necessary but I wanted to be sure that the window was deleted when closed.


Log in to reply