애니메이션 프레임워크

애니메이션 프레임워크는 GUI 요소에 애니메이션을 적용하는 쉬운 방법을 제공합니다. 이 프레임워크를 사용하면 위젯 또는 QObject 의 Qt 속성 값에 애니메이션을 적용할 수 있습니다. 프레임워크에서 제공하는 대부분의 기능은 선언적 방식으로 애니메이션을 정의할 수 있는 Qt Quick에서도 사용할 수 있으며, 선언적 방식으로 애니메이션을 정의할 수 있습니다.

이 개요에서는 프레임워크의 아키텍처를 설명하며 QObject 및 GUI 요소 애니메이션에 사용되는 일반적인 기술을 보여주는 예제를 제공합니다.

애니메이션 아키텍처

다음 다이어그램은 프레임워크에서 제공하는 가장 중요한 클래스를 보여줍니다:

여기에는 애니메이션에 필요한 기초를 제공하는 QAbstractAnimation 클래스가 포함되어 있습니다. 이 클래스는 프레임워크에서 지원하는 모든 애니메이션에 대한 일반 속성을 정의합니다. 예를 들어 애니메이션을 시작, 중지 및 일시 중지하는 기능이 있습니다. 이 클래스는 시간 변경 알림도 수신합니다.

이 프레임워크는 기본 사례인 QAbstractAnimation 을 기반으로 하는 QVariantAnimationQAnimationGroup 클래스를 추가로 제공합니다. 계층 구조의 다음 단계는 QVariantAnmiation에서 파생된 QPropertyAnimation 이며, 위젯의 Qt 프로퍼티 또는 QObject 에 애니메이션을 적용할 수 있습니다. 이 클래스는 완화 곡선을 사용하여 프로퍼티 값에 보간을 수행합니다. 이것만 있으면 애니메이션을 적용할 수 있는 Qt 속성 값을 가진 QObject 클래스만 있으면 됩니다.

참고: 애니메이션을 적용하려는 대상 객체가 QObject 또는 그 하위 클래스여야 합니다. 이는 애니메이션 프레임워크가 애니메이션 대상 객체에 대한 모든 정보를 메타 객체 시스템에 의존하기 때문에 필요합니다.

복잡한 애니메이션은 QAbstractAnimation의 트리 구조를 구축하여 만들 수 있으며, 여기서 트리는 다른 애니메이션을 포함하는 QAnimationGroup 입니다. 이러한 애니메이션 그룹에는 QParallelAnimationGroupQSequentialAnimationGroup 과 같이 다른 그룹이나 애니메이션을 나타내는 하위 그룹도 포함할 수 있습니다.

이면에서 모든 애니메이션은 실행 중인 모든 애니메이션에 대한 정보를 updates 으로 전송하는 글로벌 타이머에 의해 제어됩니다.

이러한 개별 클래스와 프레임워크에서의 역할에 대한 자세한 내용은 해당 클래스의 설명서를 참조하세요.

프레임워크에서 제공하는 클래스

이러한 클래스는 단순한 애니메이션과 복잡한 애니메이션을 만드는 데 필요한 인프라를 제공합니다.

QAbstractAnimation

모든 애니메이션의 기본

QAnimationGroup

애니메이션 그룹을 위한 추상 베이스 클래스

QEasingCurve

애니메이션 제어를 위한 완화 곡선

QParallelAnimationGroup

애니메이션의 병렬 그룹

QPauseAnimation

QSequentialAnimationGroup의 일시 정지

QPropertyAnimation

Qt 프로퍼티 애니메이션

QSequentialAnimationGroup

순차적 애니메이션 그룹

QTimeLine

애니메이션 제어를 위한 타임라인

QVariantAnimation

애니메이션의 베이스 클래스

Qt 프로퍼티 애니메이션

QPropertyAnimation 클래스는 Qt 프로퍼티에 보간을 할 수 있기 때문에 자주 사용됩니다. 실제로 이 클래스의 수퍼클래스(QVariantAnimation)는 updateCurrentValue()의 추상 구현을 제공하며, valueChanged signal 에서 변경하지 않는 한 값을 변경하지 않습니다.

이 프레임워크를 사용하면 Qt의 기존 클래스의 Qt 프로퍼티에 애니메이션을 적용할 수 있습니다. 예를 들어 QWidget 클래스는 QGraphicsView에 임베드할 수 있으며 바운드, 색상 등에 대한 프로퍼티가 있습니다. 다음 예제는 QPushButton 위젯에 애니메이션을 적용하는 방법을 보여줍니다:

#include <QApplication>
#include <QPushButton>
#include <QPropertyAnimation>

class MyButtonWidget : public QWidget
{
public:
    MyButtonWidget(QWidget *parent = nullptr);
};

MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
    QPushButton *button = new QPushButton(tr("Animated Button"), this);
    QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
    anim->setDuration(10000);
    anim->setStartValue(QPoint(0, 0));
    anim->setEndValue(QPoint(100, 250));
    anim->start();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyButtonWidget buttonAnimWidget;
    buttonAnimWidget.resize(QSize(800, 600));
    buttonAnimWidget.show();
    return a.exec();
}

이 예제에서는 QPushButtonpos Qt 프로퍼티를 애니메이션하여 화면 왼쪽 상단 모서리에서 끝 위치(250, 250)로 10초(10000밀리초) 동안 이동시킵니다.

선형 보간 방법을 사용하여 시작 값과 끝 값 사이의 애니메이션 속도를 제어합니다. 시작 값과 끝 값 사이에 다른 값을 추가하여 어떻게 보간되는지 확인해 보세요. 이번에는 QPropertyAnimation::setKeyValueAt 함수를 사용하여 이러한 값을 추가합니다:

...
anim->setDuration(10000);
anim->setKeyValueAt(0, QPoint(0, 0));
anim->setKeyValueAt(0.8, QPoint(250, 250));
anim->setKeyValueAt(1, QPoint(0, 0));
...

이 예제에서는 애니메이션이 버튼을 8초 동안 (250, 250)으로 이동하고 나머지 2초 동안 원래 위치로 다시 이동합니다. 버튼의 움직임은 이 지점 사이에서 선형 보간됩니다.

값에 세터 메서드가 있는 경우 Qt XML 프로퍼티로 선언되지 않은 QObject 값에 애니메이션을 적용할 수도 있습니다. 이러한 경우 값을 포함하는 클래스에서 새 클래스를 파생하고 설정자를 사용하여 해당 값에 대한 Qt 프로퍼티를 추가합니다.

참고: 각 Qt 프로퍼티에는 게터도 필요하므로 게터가 정의되어 있지 않은 경우 게터를 제공해야 합니다.

class MyGraphicsRectItem : public QObject, public QGraphicsRectItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
};

이 예제에서 MyGraphicsRectItemQGraphicsRectItemQObject 에서 파생되며 pos 속성을 정의합니다. QGraphicsRectItem 에서 pos 프로퍼티를 제공하지 않더라도 항목의 pos 에 애니메이션을 적용할 수 있습니다.

Qt 프로퍼티 시스템에 대한 일반적인 소개는 Qt의 프로퍼티 시스템을 참조하십시오.

애니메이션과 그래픽 뷰 프레임워크

QPropertyAnimation 를 사용하여 QObject 을 상속하지 않는 QGraphicsItem 에 애니메이션을 적용할 수도 있습니다. 이러한 경우 애니메이션을 적용하려는 그래픽 항목에서 클래스를 파생합니다. 이 파생 클래스는 QObject 형식을 상속해야 QGraphicsItem 에서 QPropertyAnimation 을 사용할 수 있습니다. 다음 예는 이 작업을 수행하는 방법을 보여줍니다:

class Pixmap : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    ...
}

참고: 이미 QObjectQGraphicsWidget 에서 파생할 수도 있습니다.

이전 섹션에서 설명한 대로 애니메이션을 적용하려는 프로퍼티를 정의해야 합니다. 파생된 클래스는 메타 객체 시스템에서 요구하므로 QObject 에서 먼저 상속해야 합니다.

곡선 완화하기

QPropertyAnimation 은 시작과 끝 프로퍼티 값 사이에 선형 보간을 수행합니다. 애니메이션에 키 값을 더 추가하는 것 외에도 경로를 변경하지 않고 0과 1 사이에서 보간 속도를 제어하는 완화 커브를 선택할 수도 있습니다.

MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
    QPushButton *button = new QPushButton(tr("Animated Button"), this);
    QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
    anim->setDuration(10000);
    anim->setStartValue(QPoint(0, 0));
    anim->setEndValue(QPoint(100, 250));
    anim->setEasingCurve(QEasingCurve::OutBounce);
    anim->start();
}

이 예제에서 애니메이션은 button 을 공처럼 튀어 오르게 하는 커브를 따릅니다. QEasingCurveQEasingCurve::Type 열거형에서 선택할 수 있는 다양한 커브 모음을 제공합니다. 사용할 수 없는 다른 커브를 사용하려면 직접 구현하여 QEasingCurve 에 등록하세요.

애니메이션 그룹화하기

애플리케이션에는 종종 두 개 이상의 애니메이션이 포함되어 있습니다. 예를 들어 두 개 이상의 그래픽 항목을 동시에 움직이거나 서로 순차적으로 움직이려고 할 수 있습니다.

QAnimationGroup-QSequentialAnimationGroupQParallelAnimationGroup- 의 서브클래스는 다른 애니메이션을 위한 컨테이너로, 이러한 애니메이션을 순차적으로 또는 병렬로 애니메이션화할 수 있습니다. QAnimationGroup 는 프로퍼티에 애니메이션을 적용하지는 않지만 주기적으로 시간 변경에 대한 알림을 받습니다. 이를 통해 애니메이션 재생 시기를 제어하는 애니메이션 그룹에 시간 변경 사항을 전달할 수 있습니다.

다음 두 예시에서는 QSequentialAnimationGroupQParallelAnimationGroup 을 모두 사용하는 방법을 보여줍니다:

MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
    QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
    QPushButton *clyde = new QPushButton(tr("Clyde"), this);

    QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
    anim1->setDuration(3000);
    anim1->setStartValue(QPoint(0, 0));
    anim1->setEndValue(QPoint(100, 250));

    QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
    anim2->setDuration(3000);
    anim2->setStartValue(QPoint(100, 250));
    anim2->setEndValue(QPoint(500, 500));

    QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
    parallelAnim->addAnimation(anim1);
    parallelAnim->addAnimation(anim2);
    parallelAnim->start();
}

병렬 그룹은 동시에 두 개 이상의 애니메이션을 재생합니다. start () 함수는 그룹의 일부인 모든 애니메이션을 시작합니다.

MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
    QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
    QPushButton *clyde = new QPushButton(tr("Clyde"), this);

    QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
    anim1->setDuration(3000);
    anim1->setStartValue(QPoint(0, 0));
    anim1->setEndValue(QPoint(100, 250));

    QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
    anim2->setDuration(3000);
    anim2->setStartValue(QPoint(0, 0));
    anim2->setEndValue(QPoint(200, 250));

    QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
    sequenceAnim->addAnimation(anim1);
    sequenceAnim->addAnimation(anim2);
    sequenceAnim->start();
}

이름에서 알 수 있듯이 QSequentialAnimationGroup 는 애니메이션을 순서대로 재생합니다. 이전 애니메이션이 끝나면 목록의 다음 애니메이션이 시작됩니다.

그룹은 그 자체로 애니메이션이므로 다른 그룹에 추가할 수 있습니다. 이렇게 하면 애니메이션 트리를 구축하여 애니메이션이 서로 연관되어 재생되는 시기를 정의할 수 있습니다.

개체 소유권

QPropertyAnimation 에는 항상 수명을 제어하는 부모가 있어야 합니다. 일반적인 애플리케이션에는 그룹화된 여러 애니메이션이 포함될 수 있으며, 애니메이션 그룹이 해당 애니메이션의 소유권을 갖습니다. 독립적인 QPropertyAnimation 에는 수명을 제어할 부모가 명시적으로 할당되어야 합니다. 다음 예시에서는 독립적인 QPropertyAnimation 인스턴스가 QApplication 인스턴스를 부모로 가지고 있는 것을 볼 수 있습니다:

#include <QApplication>
#include <QPushButton>
#include <QPropertyAnimation>

class MyButtonWidget : public QWidget
{
public:
    MyButtonWidget(QWidget *parent = nullptr);
};

MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
    QPushButton *button = new QPushButton(tr("Animated Button"), this);
    QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
    anim->setDuration(10000);
    anim->setStartValue(QPoint(0, 0));
    anim->setEndValue(QPoint(100, 250));
    anim->start();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyButtonWidget buttonAnimWidget;
    buttonAnimWidget.resize(QSize(800, 600));
    buttonAnimWidget.show();
    return a.exec();
}

참고: 애니메이션을 시작하는 동안 delete policy 을 선택하여 애니메이션의 수명을 제어할 수도 있습니다.

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