Как распространяется QCloseEvent? - PullRequest
1 голос
/ 08 мая 2020

У меня есть MainWindow, производный от QMainWindow, и я повторно реализовал обработчик closeEvent ().

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

Я закомментировал QMainWindow :: closeEvent (), чтобы проверить, что приложение выйдет без событие распространяется на базовую реализацию. Как ни странно, он выходит.

Я могу просто поместить event-> ignore () вне оператора if-else, чтобы предотвратить выход, но дело не в этом.

Другие обработчики событий, такие как keyPressEvent () don не работают должным образом без базовой реализации в своих переопределениях, но closeEvent () работает без базовой реализации. (Если, конечно, вы не переопределите все)

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

Из того, что я собранные в документации, после того, как событие было обработано виджетом, оно не распространяется дальше, если явно не разрешено. ( т.е. вызов базового keyPressEvent () в реализации дочернего keyPressEvent ())

Однако дочерний closeEvent () закроет приложение без вызова базового closeEvent () в его реализации . Похоже, он распространяется куда-то еще.

Что заставляет это происходить? Распространяется ли QCloseEvent на другие виджеты даже после того, как он уже был обработан?

1 Ответ

1 голос
/ 08 мая 2020

Какой хороший вопрос. (Я никогда об этом не думал.)

После того, как это вызвало у меня любопытство, я немного исследовал. Это хорошее в программном обеспечении OpenSource - если вы сомневаетесь, просто посмотрите исходный код. Итак, я немного покопался в woboq.org :

Сначала я искал closeEvent() в qmainwindow. cpp, но я нигде не нашел.

То же самое в qmainwindow.h .

Итак, я предполагаю QMainWindow не отменяет closeEvent().

QMainWindow является производным от QWidget, что легко можно найти в do c. или прямо в исходном коде, который у меня уже есть:

class Q_WIDGETS_EXPORT QMainWindow : public QWidget

Таким образом, я переключился на qwidget.h , который объявляет

 virtual void closeEvent(QCloseEvent *event);

(в настоящее время в строке 634 ).

Еще один щелчок, и я подошел в qwidget. cpp: 9936 :

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

Ах, да, да.

Это прекрасно объясняет, почему вызов метода базового класса

    QMainWindow::closeEvent(event);

работает так же, как простой вызов на

    event->accept();

или даже на оба.

Тем не менее, я бы предпочел вызов обработчика событий базового класса.

Я считаю это общим полезным правилом -thumb (или идиома?):

  • Если поведение базового класса должно быть расширенным , тогда вызовите обработчик событий базового класса в вашем переопределенном.

  • Если поведение базового класса должно быть заменено , тогда не вызывайте обработчик событий базового класса.

Конечно, это это общее практическое правило, и его следует e перепроверяется в зависимости от указанного c события, которое должно быть обработано.

(И в случае сомнений, все еще существует woboq.org . ..)

...