타이머

QObject는 모든 Qt 객체의 기본 클래스로, Qt에서 기본적인 타이머 기능을 제공합니다. ` QObject::startTimer()`를 사용하면 밀리초 단위의 간격을 인수로 지정하여 타이머를 시작할 수 있습니다. 이 함수는 고유한 정수형 타이머 ID를 반환합니다. 이후 해당 타이머 ID를 사용하여 ` QObject::killTimer()`를 명시적으로 호출할 때까지 타이머는 일정한 간격으로 작동합니다.

타이머 ID를 직접 처리하는 대신 QBasicTimer 를 사용할 수 있습니다. QBasicTimer 는 타이머 ID를 감싸는 값 클래스이자 RAII 래퍼입니다. QBasicTimer::start()로 타이머를 시작하고, QBasicTimer::stop()로 중지합니다(후자는 소멸 시에도 호출됩니다). QBasicTimer 를 사용하려면, timerEvent() 메서드를 클래스 내에서 재구현해야 하며(해당 클래스는 QObject 의 하위 클래스여야 함), 그 안에서 타이머 이벤트를 처리해야 합니다.

이 메커니즘이 작동하려면 애플리케이션이 이벤트 루프에서 실행되어야 합니다. QCoreApplication::exec()을 사용하여 이벤트 루프를 시작할 수 있습니다. Qt Widgets 애플리케이션에 대한 내용은 QApplication::exec()을 참조하십시오. 타이머가 발동되면 애플리케이션은 QTimerEvent 를 전송하며, 타이머 이벤트가 처리될 때까지 제어 흐름은 이벤트 루프를 벗어나게 됩니다. 이는 애플리케이션이 다른 작업을 처리하느라 바쁠 때는 타이머가 발동될 수 없음을 의미합니다. 다시 말해, 타이머의 정확도는 애플리케이션의 세분성(granularity)에 따라 달라집니다. 또한 타이머의 정확도는 기본 운영 체제와 하드웨어에 따라 달라집니다. 짧은 간격은 시스템 스케줄러에 의해 반올림되거나 지연될 수 있으며, 시스템이 바쁜 경우 모든 타이머 유형이 요청된 시간보다 늦게 타임아웃될 수 있습니다. 타이머 분해능(resolution) 및 타이머 정밀도( Qt::TimerType)에 대한 자세한 내용은 QTimer 문서를 참조하십시오.

멀티스레드 애플리케이션에서는 이벤트 루프가 있는 모든 스레드에서 타이머 메커니즘을 사용할 수 있습니다. 비 GUI 스레드에서 이벤트 루프를 시작하려면 ` QThread::exec()`를 사용하십시오. Qt는 객체의 ` thread affinity `를 사용하여 어떤 스레드가 ` QTimerEvent`를 전달할지 결정합니다. 이 때문에 모든 타이머는 반드시 해당 객체의 스레드에서 시작하고 중지해야 하며, 다른 스레드에서 객체에 대한 타이머를 시작하는 것은 불가능합니다.

타이머 기능의 주요 API는 ` QTimer`입니다. ` QTimer `는 간격을 부호 있는 정수로 저장하므로, 지원하는 최대 간격은 부호 있는 정수에 담을 수 있는 밀리초 수로 제한됩니다(실제로는 약 24일 정도의 기간에 해당합니다).

Qt 6.8에서는 QChronoTimer 클래스가 도입되었습니다. 두 클래스의 주요 차이점은 QChronoTimer 이 더 넓은 간격 범위와 더 높은 정밀도를 지원한다는 점입니다(std::chrono::nanoseconds). QTimer 의 경우 지원되는 최대 간격은 ±24일인 반면, QChronoTimer 의 경우 ±292년입니다. 밀리초 단위의 분해능과 ±24일의 범위만 필요한 경우, QTimer 를 계속 사용할 수 있습니다. QChronoTimer 가 존재하는 주된 이유는, QTimer 의 정밀도를 std::chrono::nanoseconds 로 변경할 경우 바이너리 호환성이 깨지기 때문입니다.

QTimer 이 클래스는 타이머가 작동할 때 신호를 발생시키는 일반 타이머를 제공하며, QObject 를 상속받아 대부분의 Qt 프로그램의 소유권 구조에 잘 부합합니다. 일반적인 사용 방법은 다음과 같습니다:

        QTimer *timer = new QTimer(1s, this);
        connect(timer, &QTimer::timeout, this, &MyWidget::processOneThing);
        timer->start();
        auto *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &MyWidget::processOneThing);
        timer->setInterval(1s);
        timer->start();

QTimer 객체를 this 객체의 자식 객체로 설정하여, this 가 소멸될 때 타이머도 함께 소멸되도록 합니다. 다음으로, timeout() 신호를 작업을 수행할 슬롯에 연결하고, 타이머 간격은 생성자에 전달하거나 나중에 setInterval()을 사용하여 설정할 수 있습니다.

QTimer 또한 일회성 타이머를 위한 정적 함수도 제공합니다. 예를 들어:

        MyWidget widget;
        QTimer::singleShot(200ms, &widget, &MyWidget::updateCaption);

이 코드 줄이 실행된 후 200ms가 지나면 updateCaption() 슬롯이 호출됩니다.

QTimer 가 작동하려면 애플리케이션에 이벤트 루프가 있어야 합니다. 즉, 어딘가에서 ` QCoreApplication::exec()`를 호출해야 합니다. 타이머 이벤트는 이벤트 루프가 실행 중일 때만 전달됩니다.

멀티스레드 애플리케이션에서는 이벤트 루프가 있는 모든 스레드에서 QTimer 를 사용할 수 있습니다. GUI가 아닌 스레드에서 이벤트 루프를 시작하려면 QThread::exec()를 사용하십시오. Qt는 타이머의 ` thread affinity `를 사용하여 ` timeout()` 신호를 발산할 스레드를 결정합니다. 이 때문에 타이머는 해당 스레드 내에서 시작하고 중지해야 하며, 다른 스레드에서 타이머를 시작하는 것은 불가능합니다.

'Analog Clock' 예제는 QTimer 를 사용하여 위젯을 일정한 간격으로 다시 그리는 방법을 보여줍니다. AnalogClock 의 구현에서 발췌한 내용입니다:

AnalogClock::AnalogClock(QWidget *parent)
    : QWidget(parent)
{
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));
    timer->start(1000);

    setWindowTitle(tr("Analog Clock"));
    resize(200, 200);
}

QTimer 는 매초마다 QWidget::update() 슬롯을 호출하여 시계 디스플레이를 갱신합니다.

© 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.