Python Tkinter - 5. 그래픽과 애니메이션

2025. 2. 28. 14:37프로그래밍 언어/Python

5. 그래픽과 애니메이션

이번 주차에서는 Tkinter의 Canvas 위젯을 활용하여 도형을 그리는 방법, 드래그 앤 드롭 구현, 애니메이션 적용 등을 학습합니다.
또한 드로잉 툴, 데이터 시각화, 애니메이션을 활용한 시계 및 2D 게임 개발을 실습합니다.


이론

1. Canvas 위젯

Tkinter의 Canvas 위젯은 GUI에서 그래픽 요소를 표현하는 가장 강력한 도구입니다. 이를 통해 선, 사각형, 원 등의 기본 도형을 그리거나, 객체를 이동하는 다양한 기능을 구현할 수 있습니다.

1) 도형 그리기 (선, 사각형, 원)

import tkinter as tk

root = tk.Tk()
root.title("Canvas 도형 그리기")

canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()

# 선 그리기
canvas.create_line(50, 50, 200, 50, fill="black", width=2)

# 사각형 그리기
canvas.create_rectangle(50, 100, 200, 200, fill="blue")

# 원 그리기
canvas.create_oval(250, 50, 350, 150, fill="red")

root.mainloop()

Canvas를 활용하여 선, 사각형, 원을 생성하는 기본적인 방법을 익힙니다.


2) 드래그 앤 드롭 구현

Canvas 객체를 마우스로 클릭 후 드래그하여 이동할 수 있도록 이벤트를 설정합니다.

import tkinter as tk

def start_move(event):
    """ 드래그 시작 위치 저장 """
    global start_x, start_y
    start_x, start_y = event.x, event.y

def on_move(event):
    """ 객체 이동 """
    global start_x, start_y
    dx, dy = event.x - start_x, event.y - start_y
    canvas.move("movable", dx, dy)
    start_x, start_y = event.x, event.y  # 새로운 위치 갱신

root = tk.Tk()
root.title("드래그 앤 드롭")

canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()

rect = canvas.create_rectangle(50, 50, 150, 150, fill="green", tags="movable")
canvas.tag_bind("movable", "<ButtonPress-1>", start_move)
canvas.tag_bind("movable", "<B1-Motion>", on_move)

root.mainloop()

이제 사각형을 클릭 후 마우스로 드래그하여 이동할 수 있습니다.


2. 애니메이션

Tkinter의 after() 메서드를 활용하여 주기적으로 함수를 호출함으로써 애니메이션을 구현할 수 있습니다.

1) 기본 애니메이션

import tkinter as tk

def move_circle():
    """ 원이 오른쪽으로 이동하는 애니메이션 """
    global x, animation_id
    x += 5
    if x > 350:
        stop_animation()
        return
    canvas.move(circle, 5, 0)
    animation_id = root.after(50, move_circle)

def start_animation():
    """ 애니메이션 시작 """
    global animation_id
    animation_id = root.after(50, move_circle)

def stop_animation():
    """ 애니메이션 멈춤 """
    global animation_id
    if animation_id:
        root.after_cancel(animation_id)
        animation_id = None

root = tk.Tk()
root.title("애니메이션")

canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()

x = 50
animation_id = None

circle = canvas.create_oval(x, 100, x+50, 150, fill="blue")

# 버튼 추가
start_btn = tk.Button(root, text="시작", command=start_animation)
start_btn.pack(side=tk.LEFT, padx=5)
stop_btn = tk.Button(root, text="멈춤", command=stop_animation)
stop_btn.pack(side=tk.LEFT, padx=5)

root.mainloop()

"시작" 버튼을 클릭하면 원이 오른쪽으로 이동하고, "멈춤" 버튼을 클릭하면 멈춥니다.


실습

1. 드로잉 툴

사용자가 마우스를 이용하여 선을 그릴 수 있는 드로잉 애플리케이션을 구현합니다.

import tkinter as tk
from tkinter import colorchooser

def choose_color():
    """ 색상 선택 다이얼로그 """
    selected_color = colorchooser.askcolor(title="색상 선택")[1]
    if selected_color:
        color.set(selected_color)

def draw(event):
    """ 사용자가 마우스를 움직이면 선을 그림 """
    x, y = event.x, event.y
    canvas.create_oval(x-2, y-2, x+2, y+2, fill=color.get(), outline=color.get())

def clear_canvas():
    """ 캔버스 초기화 (지우기) """
    canvas.delete("all")

root = tk.Tk()
root.title("드로잉 툴")

color = tk.StringVar(value="black")

toolbar = tk.Frame(root)
toolbar.pack(fill=tk.X, pady=5)

color_btn = tk.Button(toolbar, text="색상 선택", command=choose_color)
color_btn.pack(side=tk.LEFT, padx=5)

clear_btn = tk.Button(toolbar, text="지우기", command=clear_canvas)
clear_btn.pack(side=tk.LEFT, padx=5)

canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()
canvas.bind("<B1-Motion>", draw)

root.mainloop()

마우스를 움직이면 색상이 적용된 선을 그릴 수 있으며, 색상 선택 및 지우기 기능을 포함합니다.


2. 데이터 시각화 (막대 그래프)

import random

def draw_bar_chart():
    data = [random.randint(50, 200) for _ in range(5)]
    for i, height in enumerate(data):
        canvas.create_rectangle(50 + i * 60, 300 - height, 90 + i * 60, 300, fill="blue")

root = tk.Tk()
root.title("데이터 시각화")

canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()

draw_bar_chart()

root.mainloop()

랜덤한 높이의 막대 그래프를 생성할 수 있습니다.


3. 애니메이션 애플리케이션 (디지털 시계)

import time

def update_clock():
    current_time = time.strftime("%H:%M:%S")
    label.config(text=current_time)
    root.after(1000, update_clock)

root = tk.Tk()
root.title("디지털 시계")

label = tk.Label(root, font=("Arial", 24))
label.pack()

update_clock()

root.mainloop()

실시간으로 시간이 업데이트되는 디지털 시계를 구현합니다.


과제: 2D 게임 개발

1. 벽돌 깨기 게임 (패들 움직이기)

def move_paddle(event):
    x = event.x
    canvas.coords(paddle, x-50, 280, x+50, 300)

root = tk.Tk()
root.title("벽돌 깨기 게임")

canvas = tk.Canvas(root, width=400, height=300, bg="black")
canvas.pack()

paddle = canvas.create_rectangle(175, 280, 225, 300, fill="white")
root.bind("<Motion>", move_paddle)

root.mainloop()

패들이 마우스에 따라 좌우로 움직이며, 추가적으로 공과 충돌 감지를 구현할 수 있습니다.


📌 정리

  • Canvas 활용: 기본 도형 그리기, 드래그 앤 드롭 구현
  • 애니메이션: after() 메서드를 활용한 애니메이션 구현
  • 실습: 드로잉 툴, 데이터 시각화, 디지털 시계 제작
  • 과제: 벽돌 깨기 또는 스네이크 게임 구현