이벤트 시스템
Qt에서 이벤트는 추상 클래스 ` QEvent `에서 파생된 객체로, 애플리케이션 내부에서 발생했거나 애플리케이션이 인지해야 할 외부 활동의 결과로 발생한 상황을 나타냅니다. 이벤트는 ` QObject ` 하위 클래스의 모든 인스턴스가 수신하고 처리할 수 있지만, 특히 위젯과 밀접한 관련이 있습니다. 이 문서는 일반적인 애플리케이션에서 이벤트가 전달되고 처리되는 방식을 설명합니다.
이벤트 전달 방식
이벤트가 발생하면 Qt는 적절한 ` QEvent ` 하위 클래스의 인스턴스를 생성하여 이를 나타내는 이벤트 객체를 만들고, ` event()` 함수를 호출하여 특정 ` QObject `(또는 그 하위 클래스 중 하나) 인스턴스로 전달합니다.
이 함수는 이벤트 자체를 처리하지 않으며, 전달된 이벤트의 유형에 따라 해당 특정 유형의 이벤트에 대한 이벤트 핸들러를 호출하고, 이벤트가 수락되었는지 무시되었는지에 따라 응답을 보냅니다.
QMouseEvent 나 QKeyEvent 와 같은 일부 이벤트는 윈도우 시스템에서 발생하고, QTimerEvent 와 같은 일부 이벤트는 다른 출처에서 발생하며, 일부는 애플리케이션 자체에서 발생합니다.
이벤트 유형
대부분의 이벤트 유형에는 특수한 클래스가 있으며, 특히 ` QResizeEvent`, ` QPaintEvent`, ` QMouseEvent`, ` QKeyEvent`, ` QCloseEvent` 등이 있습니다. 각 클래스는 ` QEvent `의 서브클래스이며, 이벤트별 함수를 추가합니다. 예를 들어, ` QResizeEvent `는 ` size()` 및 ` oldSize()`를 추가하여 위젯이 자신의 크기가 어떻게 변경되었는지 파악할 수 있게 합니다.
일부 클래스는 하나 이상의 실제 이벤트 유형을 지원합니다. QMouseEvent 는 마우스 버튼 누르기, 더블 클릭, 이동 및 기타 관련 작업을 지원합니다.
각 이벤트에는 QEvent::Type 에 정의된 관련 유형이 있으며, 이를 런타임 유형 정보의 편리한 소스로 사용하여 주어진 이벤트 객체가 어떤 하위 클래스에서 생성되었는지 신속하게 파악할 수 있습니다.
프로그램은 다양하고 복잡한 방식으로 반응해야 하므로, Qt의 이벤트 전달 메커니즘은 유연합니다. ` QCoreApplication::notify()`에 대한 문서에는 전체 내용이 간결하게 설명되어 있으며, Qt Quarterly 기사 “Another Look at Events”에서는 이를 다소 덜 간결하게 재조명하고 있습니다. 여기서는 95%의 애플리케이션에 충분한 수준까지 설명하겠습니다.
이벤트 핸들러
이벤트가 전달되는 일반적인 방식은 가상 함수를 호출하는 것입니다. 예를 들어, ` QPaintEvent `는 ` QWidget::paintEvent()`를 호출하여 전달됩니다. 이 가상 함수는 일반적으로 위젯을 다시 그리면서 적절하게 반응할 책임을 집니다. 가상 함수 구현에서 필요한 모든 작업을 수행하지 않는 경우, 기저 클래스의 구현을 호출해야 할 수도 있습니다.
예를 들어, 다음 코드는 사용자 정의 체크박스 위젯에서 마우스 왼쪽 버튼 클릭을 처리하는 동시에, 그 외의 모든 버튼 클릭은 기본 QCheckBox 클래스로 전달합니다:
void MyCheckBox::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
// handle left mouse button here
} else {
// pass on other buttons to base class
QCheckBox::mousePressEvent(event);
}
}기초 클래스의 함수를 완전히 대체하려면 모든 기능을 직접 구현해야 합니다. 그러나 기초 클래스의 기능을 확장하기만 원하는 경우에는 원하는 부분만 구현하고, 처리하지 않으려는 경우에 대해서는 기초 클래스를 호출하여 기본 동작을 얻으면 됩니다.
때로는 특정 이벤트에 대한 함수가 없거나, 해당 함수만으로는 충분하지 않은 경우가 있습니다. 가장 흔한 예로는 Tab 키 누름이 있습니다. 일반적으로 ` QWidget `는 키보드 포커스를 이동하기 위해 이를 가로채지만, 일부 위젯은 자체적으로 Tab 키를 사용해야 합니다.
이러한 객체는 일반적인 이벤트 핸들러인 ` QObject::event()`를 재구현하여, 일반적인 처리 전이나 후에 자체 이벤트 처리를 수행하거나, 해당 함수를 완전히 대체할 수 있습니다. Tab 키를 해석하면서도 애플리케이션별 사용자 정의 이벤트를 모두 갖는 매우 특이한 위젯의 경우, 다음과 같은 ` event()` 함수를 포함할 수 있습니다:
bool MyWidget::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Tab) {
// special tab handling here
return true;
}
} else if (event->type() == MyCustomEventType) {
MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);
// custom event handling here
return true;
}
return QWidget::event(event);
}QWidget::event()는 처리되지 않은 모든 경우에 여전히 호출되며, 반환 값은 이벤트가 처리되었는지 여부를 나타냅니다. true 값을 반환하면 이벤트가 다른 객체로 전달되는 것을 방지합니다.
이벤트 필터
때로는 객체가 다른 객체로 전달되는 이벤트를 확인하거나, 경우에 따라 가로채야 할 필요가 있습니다. 예를 들어, 대화 상자에서는 특정 위젯에 대한 키 입력을 필터링해야 하는 경우가 흔합니다. 예를 들어, Return 키 처리를 수정하기 위해서입니다.
QObject::installEventFilter() 함수는 이벤트 필터를 설정하여 이를 가능하게 하며, 지정된 필터 객체가 QObject::eventFilter() 함수 내에서 대상 객체에 대한 이벤트를 수신하도록 합니다. 이벤트 필터는 대상 객체보다 먼저 이벤트를 처리할 수 있으므로, 필요에 따라 이벤트를 검사하고 버릴 수 있습니다. 기존 이벤트 필터는 QObject::removeEventFilter() 함수를 사용하여 제거할 수 있습니다.
필터 객체의 ` eventFilter()` 구현이 호출되면, 해당 객체는 이벤트를 수락하거나 거부할 수 있으며, 이벤트의 추가 처리를 허용하거나 거부할 수 있습니다. 모든 이벤트 필터가 이벤트의 후속 처리를 허용할 경우(각각 ` false`를 반환), 해당 이벤트는 대상 객체 자체로 전송됩니다. 필터 중 하나가 처리를 중단할 경우(` true`를 반환), 대상 객체와 그 이후의 모든 이벤트 필터는 해당 이벤트를 전혀 접할 수 없습니다.
bool FilterObject::eventFilter(QObject *object, QEvent *event)
{
if (object == target && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Tab) {
// Special tab handling
return true;
} else
return false;
}
return false;
}위의 코드는 특정 대상 위젯으로 전송되는 Tab 키 누름 이벤트를 가로채는 또 다른 방법을 보여줍니다. 이 경우, 필터는 관련 이벤트를 처리하고 true 을 반환하여 이벤트가 더 이상 처리되지 않도록 합니다. 다른 모든 이벤트는 무시되며, 필터는 false 을 반환하여 대상 위젯에 설치된 다른 이벤트 필터를 통해 해당 이벤트가 대상 위젯으로 전달되도록 허용합니다.
QApplication 또는 QCoreApplication 객체에 이벤트 필터를 설치하여 애플리케이션 전체의 모든 이벤트를 필터링할 수도 있습니다. 이러한 전역 이벤트 필터는 객체별 필터보다 먼저 호출됩니다. 이는 매우 강력한 기능이지만, 애플리케이션 전체의 모든 이벤트 전달 속도를 저하시킵니다. 따라서 일반적으로 앞서 설명한 다른 기법을 사용하는 것이 좋습니다.
이벤트 전송
많은 애플리케이션은 자체 이벤트를 생성하고 전송하기를 원합니다. 적절한 이벤트 객체를 생성하고 ` QCoreApplication::sendEvent()` 및 ` QCoreApplication::postEvent()`를 통해 전송함으로써, Qt의 기본 이벤트 루프와 정확히 동일한 방식으로 이벤트를 전송할 수 있습니다.
sendEvent()는 이벤트를 즉시 처리합니다. 이 함수가 반환될 때쯤이면 이벤트 필터나 객체 자체가 이미 해당 이벤트를 처리한 상태입니다. 많은 이벤트 클래스에는 isAccepted()라는 함수가 있는데, 이 함수는 마지막으로 호출된 핸들러가 이벤트를 수락했는지 거부했는지 여부를 알려줍니다.
postEvent()는 이벤트를 큐에 게시하여 나중에 디스패치되도록 합니다. Qt의 메인 이벤트 루프가 다음에 실행될 때, 일부 최적화를 거쳐 게시된 모든 이벤트를 디스패치합니다. 예를 들어, 여러 개의 크기 조정 이벤트가 있는 경우, 이들은 하나의 이벤트로 압축됩니다. 페인트 이벤트에도 동일한 원리가 적용됩니다. ` QWidget::update()`는 ` postEvent()`를 호출하며, 이는 깜빡임을 제거하고 중복된 재그리기 작업을 방지함으로써 속도를 높여줍니다.
postEvent()는 객체 초기화 중에도 사용되는데, 이는 게시된 이벤트가 일반적으로 객체 초기화가 완료된 직후에 디스패치되기 때문입니다. 위젯을 구현할 때, 이벤트가 위젯의 수명 주기 초기에 전달될 수 있다는 점을 인식하는 것이 중요합니다. 따라서 생성자에서 이벤트를 수신할 가능성이 생기기 전에 멤버 변수를 미리 초기화해야 합니다.
사용자 정의 유형의 이벤트를 생성하려면 QEvent::User 보다 큰 이벤트 번호를 정의해야 하며, 사용자 정의 이벤트에 대한 특정 정보를 전달하기 위해 QEvent 의 서브클래스를 만들어야 할 수도 있습니다. 자세한 내용은 QEvent 문서를 참조하십시오.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.