PyQt개발강좌, QPropertyAnimation과 QGraphicsView 애니메이션

PyQt는 Python 프로그래밍 언어에 Qt를 기반으로 한 GUI 툴킷으로, 풍부한 사용자 인터페이스를 만들 수 있는 강력한 도구입니다. 본 글에서는 PyQt의 애니메이션 기능 중 QPropertyAnimationQGraphicsView를 활용한 애니메이션 구현 방법에 대해 자세히 설명하겠습니다.

1. PyQt와 애니메이션의 개요

애니메이션은 그래픽 사용자 인터페이스에서 사용자 경험을 향상시키는 강력한 도구입니다. PyQt에서는 QPropertyAnimation 클래스를 사용하여 다양한 위젯의 속성을 시간에 따라 부드럽게 변경할 수 있습니다. 이와 연계하여 QGraphicsView는 2D 그래픽 요소를 쉽게 다룰 수 있게 해주는 클래스입니다. 두 클래스를 결합하면 더욱 매력적인 애니메이션을 구현할 수 있습니다.

2. QPropertyAnimation

QPropertyAnimation은 위젯의 속성을 애니메이션 효과로 변화시킬 수 있는 클래스입니다. 예를 들어, 버튼의 위치나 크기를 애니메이션으로 변경함으로써 시각적으로 더 매력적인 UI를 구성할 수 있습니다.

2.1 QPropertyAnimation 기본 사용법

QPropertyAnimation을 사용하기 위해서는 먼저 Qt 위젯을 생성한 후, 해당 위젯의 속성을 애니메이션 할 수 있도록 설정합니다. 다음은 버튼의 위치를 변화시키는 간단한 예제입니다.

예제 코드


import sys
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QPropertyAnimation, QRect

class AnimationExample(QWidget):
    def __init__(self):
        super().__init__()

        self.button = QPushButton("Click Me!", self)
        self.button.setGeometry(50, 50, 100, 40)

        self.animation = QPropertyAnimation(self.button, b"geometry")
        self.animation.setDuration(1000)
        self.animation.setStartValue(QRect(50, 50, 100, 40))
        self.animation.setEndValue(QRect(200, 50, 100, 40))
        self.animation.setLoopCount(-1)  # 무한 반복

        self.button.clicked.connect(self.start_animation)

        layout = QVBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout)

    def start_animation(self):
        self.animation.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = AnimationExample()
    window.setGeometry(100, 100, 400, 200)
    window.setWindowTitle("QPropertyAnimation 예제")
    window.show()
    sys.exit(app.exec_())
        

위 코드에서는 QPropertyAnimation을 설정하여 버튼의 위치를 애니메이션 효과로 변경합니다. 버튼을 클릭하면 시작하는 애니메이션은 1초에 걸쳐 버튼이 왼쪽에서 오른쪽으로 이동하는 모습입니다. setLoopCount(-1)을 통해 애니메이션을 무한 반복하도록 설정했습니다.

3. QGraphicsView

QGraphicsView는 2D 그래픽 장면을 표시하기 위한 위젯으로, 여러 개의 그래픽 아이템을 관리하고 그릴 수 있는 기능을 제공합니다. QGraphicsScene과 결합하여 다양한 그래픽 요소를 효과적으로 구현할 수 있습니다. 특히, 애니메이션과 함께 사용하면 더 매력적인 비주얼 효과를 낼 수 있습니다.

3.1 QGraphicsView 기본 사용법

QGraphicsView를 사용하기 위해서는 먼저 QGraphicsScene을 생성하고, 그 위에 다양한 아이템을 추가합니다. 다음은 간단한 원을 QGraphicsView에 추가하고 그 크기를 변경하는 예제입니다.

예제 코드


import sys
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsEllipseItem, QGraphicsScene
from PyQt5.QtCore import QPropertyAnimation

class GraphicsViewExample(QGraphicsView):
    def __init__(self):
        super().__init__()

        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)

        self.circle = QGraphicsEllipseItem(0, 0, 100, 100)
        self.circle.setBrush(Qt.blue)
        self.scene.addItem(self.circle)

        self.animation = QPropertyAnimation(self.circle, b"rect")
        self.animation.setDuration(1000)
        self.animation.setStartValue(self.circle.rect())
        self.animation.setEndValue(self.circle.rect().adjusted(-20, -20, 20, 20))
        self.animation.setLoopCount(-1)  # 무한 반복

        self.start_animation()

    def start_animation(self):
        self.animation.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    view = GraphicsViewExample()
    view.setGeometry(100, 100, 400, 300)
    view.setWindowTitle("QGraphicsView 애니메이션 예제")
    view.show()
    sys.exit(app.exec_())
        

위 예제에서 QGraphicsEllipseItem을 사용하여 100×100 크기의 원을 그리고, 그 크기를 애니메이션으로 변경합니다. 애니메이션은 원의 크기를 20픽셀씩 줄였다가 늘리는 과정을 무한히 반복합니다.

4. QPropertyAnimation과 QGraphicsView 결합하기

QPropertyAnimation과 QGraphicsView를 결합하여 좀 더 복잡한 애니메이션을 구현할 수 있습니다. 예를 들어, 여러 개의 그래픽 아이템을 생성하고 동시에 움직이는 애니메이션을 추가해 보겠습니다.

4.1 복합 애니메이션 예제

이번 예제에서는 다양한 색상의 원들이 화면을 왔다 갔다 하는 애니메이션을 구현해 보겠습니다.

예제 코드


import sys
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsEllipseItem, QGraphicsScene
from PyQt5.QtCore import QPropertyAnimation, Qt

class ComplexAnimationExample(QGraphicsView):
    def __init__(self):
        super().__init__()

        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)

        self.circles = []
        for i in range(5):
            circle = QGraphicsEllipseItem(0, 0, 50, 50)
            circle.setBrush(Qt.GlobalColor((i+1)*50, 0, 255-(i+1)*50))
            circle.setPos(50 + i*60, 100)
            self.scene.addItem(circle)
            self.circles.append(circle)

            animation = QPropertyAnimation(circle, b"pos")
            animation.setDuration(2000)
            animation.setStartValue(circle.pos())
            animation.setEndValue(circle.pos() + QtCore.QPointF(300, 0))
            animation.setLoopCount(-1)  # 무한 반복
            animation.start()

    def start_animation(self):
        for circle in self.circles:
            animation = QPropertyAnimation(circle, b"pos")
            animation.setDuration(1000)
            animation.setStartValue(circle.pos())
            animation.setEndValue(circle.pos() + QtCore.QPointF(300, 0))
            animation.setLoopCount(-1)
            animation.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    view = ComplexAnimationExample()
    view.setGeometry(100, 100, 800, 400)
    view.setWindowTitle("복합 애니메이션 예제")
    view.show()
    sys.exit(app.exec_())
        

이 예제에서는 5개의 원을 생성하고, 각각의 원이 수평으로 300픽셀 이동하는 애니메이션을 설정합니다. 각 원은 서로 다르게 색상을 지정하였으며, 애니메이션을 통해 화면에서 왔다 갔다 하는 모습을 구현합니다.

5. 사용자 입력과 애니메이션

애니메이션을 사용하여 사용자 경험을 더욱 향상시킬 수 있습니다. 예를 들어, 사용자가 버튼 클릭을 통해 애니메이션을 시작하거나, 애니메이션의 상태를 변경할 수 있습니다.

5.1 사용자 입력을 통한 애니메이션 제어

사용자가 입력한 값을 받아 애니메이션의 속도, 방향 등을 변경하는 예제를 살펴보겠습니다.

예제 코드


import sys
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsEllipseItem, QGraphicsScene, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QPropertyAnimation, Qt

class InteractiveAnimationExample(QWidget):
    def __init__(self):
        super().__init__()

        self.view = QGraphicsView(self)
        self.scene = QGraphicsScene(self)
        self.view.setScene(self.scene)

        self.circle = QGraphicsEllipseItem(0, 0, 50, 50)
        self.circle.setBrush(Qt.red)
        self.scene.addItem(self.circle)

        self.startButton = QPushButton("애니메이션 시작", self)
        self.startButton.clicked.connect(self.start_animation)

        layout = QVBoxLayout()
        layout.addWidget(self.view)
        layout.addWidget(self.startButton)
        self.setLayout(layout)

    def start_animation(self):
        self.animation = QPropertyAnimation(self.circle, b"pos")
        self.animation.setDuration(2000)
        self.animation.setStartValue(self.circle.pos())
        self.animation.setEndValue(self.circle.pos() + QtCore.QPointF(300, 0))
        self.animation.setLoopCount(-1)  # 무한 반복
        self.animation.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = InteractiveAnimationExample()
    window.setGeometry(100, 100, 800, 400)
    window.setWindowTitle("사용자 입력을 통한 애니메이션 제어")
    window.show()
    sys.exit(app.exec_())
        

여기에서는 버튼 클릭을 통해 애니메이션이 시작되도록 구현하였습니다. 버튼을 클릭하면 원이 오른쪽으로 움직이는 애니메이션이 실행되며, 사용자가 애니메이션을 직접 조작할 수 있는 인터페이스를 제공합니다.

6. 애니메이션 효과를 향상시키기 위한 팁

애니메이션을 사용할 때는 아래의 몇 가지 팁을 고려하여 더욱 매력적인 애니메이션을 만들 수 있습니다:

  • 타이밍 조절: 애니메이션의 속도를 조절하여 부드러운 움직임을 만들어 보세요.
  • 다양한 효과: 동시에 여러 애니메이션을 적용하여 복잡한 효과를 만들어 보세요.
  • 이벤트 기반 애니메이션: 사용자 입력에 따라 애니메이션을 변화시켜 사용자 경험을 증가시키세요.
  • 속성 조합: 여러 속성을 동시에 애니메이션할 수 있습니다.

결론

PyQt의 애니메이션 기능을 활용하면 더욱 생동감 있는 GUI를 구현할 수 있습니다. QPropertyAnimationQGraphicsView를 이용하여 다양한 애니메이션 효과를 쉽게 적용할 수 있으며, 이를 통해 사용자 경험을 한층 더 향상시킬 수 있습니다. 본 강좌에서 소개한 예제들을 기반으로, 여러분만의 창의적인 애니메이션을 만들어 보시기 바랍니다.