1
votes

I have a MainWindow derived from QMainWindow and I re-implemented the closeEvent() handler.

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (this->okToContinue()) {
        this->writeSettings();
        //event->accept();
        QMainWindow::closeEvent(event); // will work just fine even if this line omitted
    } else {
        event->ignore();
    }
}

I've commented out the QMainWindow::closeEvent() to test the app will exit without the event propagating to the base implementation. Weirdly enough, it does exit.

I can just put event->ignore() outside of the if-else statement to prevent exiting but that's not the point.

Other event handlers such as keyPressEvent() don't work properly without the base implementation in their overrides but the closeEvent() does work without the base implementation. (Unless, of course, you reimplement everything)

void LineEdit::keyPressEvent(QCloseEvent *event)
{
    QLineEdit::keyPressEvent(event); // will not show text in the widget if omitted
}

From what I've gathered in the documentation, once an event was handled by a widget, it does not propagate any further, unless explicitly allowed. (i.e. invoking the base's keyPressEvent() in the implementation of the child's keyPressEvent())

However a child's closeEvent() will close the application without invoking the base's closeEvent() in it's implementation. Seems like it propagates to somewhere else.

What makes this happen? Does QCloseEvent propagate to other widgets even after it was already handled?

1

1 Answers

1
votes

What a nice question. (I never have thought about this.)

After this raised my curiosity, I investigated a bit. That's the nice about OpenSource software – if you are in doubt just have a look into source code. So, I digged a bit on woboq.org:

First I looked for closeEvent() in qmainwindow.cpp but I couldn't find it anywhere.

The same in qmainwindow.h.

So, I assume QMainWindow doesn't override closeEvent().

QMainWindow is derived from QWidget as easily can be found in the doc. or directly in the source code which I have already at hand:

class Q_WIDGETS_EXPORT QMainWindow : public QWidget

Thus, I switched to qwidget.h which declares

 virtual void closeEvent(QCloseEvent *event);

(currently in line 634).

One click again and I approached in qwidget.cpp:9936:

void QWidget::closeEvent(QCloseEvent *event)
{
    event->accept();
}

Ah, yepp.

This explains nicely why the call of base class method

    QMainWindow::closeEvent(event);

works as well as a simple call to

    event->accept();

or even both.

Though, I would prefer the call of the base class event handler.

I consider this as the general useful rule-of-thumb (or idiom?):

  • If the behavior of base class shall be extended then call the base class event handler in your overridden.

  • If the behavior of base class shall be replaced then don't call the base class event handler.

Of course, this is a general rule of thumb and should be re-checked depending on the specific event which has to be handled.

(And in case of doubts, there still is woboq.org...)