구현

파이썬으로 그림판 만들기 (5단계: 지우개)

cs newbie 2025. 4. 16. 15:17

▣ 5단계: 지우개 기능과 실행 취소 기능 추가

✔ 목표   

- 지우개 버튼을 누르면 배경색(흰색)으로 선을 그려 지우는 효과
- 지우개도 선 굵기 조절 슬라이더에 반응
- `Ctrl + Z` 키를 누르면 마지막으로 그린 선을 되돌릴 수 있음 (실행 취소)

 

✔ 코드  

import tkinter as tk
from tkinter import colorchooser

# ============================
#       드로잉 함수들
# ============================

def start_draw(event):
    """
    마우스를 누를 때 호출됨.
    현재 좌표 저장 및 새로운 선 묶음(stroke) 리스트 시작.
    """
    global last_x, last_y, current_stroke
    last_x, last_y = event.x, event.y
    current_stroke = []  # 새로운 stroke 시작

def draw(event):
    """
    마우스를 누른 채 이동할 때 호출됨.
    이전 좌표부터 현재 좌표까지 선을 그리고, 해당 선의 ID를 저장.
    """
    global last_x, last_y
    color = current_color.get()
    width = brush_size.get()
    line = canvas.create_line(last_x, last_y, event.x, event.y,
                              fill=color, width=width, capstyle=tk.ROUND, smooth=True)
    current_stroke.append(line)  # 현재 stroke에 선 ID 추가
    last_x, last_y = event.x, event.y

def end_draw(event):
    """
    마우스를 뗄 때 호출됨.
    하나의 stroke가 완성되면 전체 stroke 리스트에 저장.
    """
    if current_stroke:
        drawn_lines.append(current_stroke)

# ============================
#     슬라이더 ↔ 드롭다운 연동
# ============================

def update_from_slider(value):
    dropdown_var.set(int(value))

def update_from_dropdown(*args):
    brush_size.set(dropdown_var.get())

# ============================
#     색상 선택 함수
# ============================

def choose_color():
    color_code = colorchooser.askcolor(title="선 색상 선택")
    if color_code[1]:
        current_color.set(color_code[1])
        color_preview.config(bg=color_code[1])

# ============================
#     지우개 기능
# ============================

def use_eraser():
    """
    지우개 버튼 클릭 시 호출됨. 현재 색상을 흰색으로 설정.
    실제로는 흰색 선을 그려 지우는 효과.
    """
    current_color.set("white")
    color_preview.config(bg="white")

# ============================
#     실행 취소 기능
# ============================

def undo(event=None):
    """
    Ctrl+Z 입력 시 호출됨.
    마지막 stroke(선들의 묶음)를 캔버스에서 삭제.
    """
    if drawn_lines:
        last_stroke = drawn_lines.pop()
        for line_id in last_stroke:
            canvas.delete(line_id)

# ============================
#         GUI 생성
# ============================

root = tk.Tk()
root.title("그림판")

# 전역 변수들 초기화
current_color = tk.StringVar(value="black")  # 현재 선택된 색상
brush_size = tk.IntVar(value=2)               # 브러시 굵기
current_stroke = []                           # 현재 그리고 있는 stroke
drawn_lines = []                              # 그려진 stroke들의 리스트

# 단축키 등록
root.bind("<Control-z>", undo)

# ▶ 상단 툴바 프레임

top_frame = tk.Frame(root)
top_frame.pack(side="top", fill="x", pady=5, padx=10)

# ▶ 왼쪽 도구 그룹: 선 굵기 설정 (슬라이더 + 드롭다운)
left_tool_frame = tk.Frame(top_frame)
left_tool_frame.pack(side="left")

slider = tk.Scale(left_tool_frame, from_=1, to=20, orient="horizontal",
                  variable=brush_size, label="선 굵기",
                  command=update_from_slider)
slider.pack(side="left", padx=5)

dropdown_var = tk.IntVar(value=2)
dropdown_options = [1, 2, 4, 8, 12, 16, 20]
dropdown_menu = tk.OptionMenu(left_tool_frame, dropdown_var, *dropdown_options)
dropdown_menu.config(width=6)
dropdown_var.trace_add("write", update_from_dropdown)
dropdown_menu.pack(side="left", padx=5)

# ▶ 오른쪽 도구 그룹: 색상 선택, 지우개 버튼
right_tool_frame = tk.Frame(top_frame)
right_tool_frame.pack(side="right")

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

color_preview = tk.Label(right_tool_frame, bg=current_color.get(), width=3,
                         relief="solid", borderwidth=1, cursor="hand2")
color_preview.pack(side="left", padx=3)
color_preview.bind("<Button-1>", lambda e: choose_color())

eraser_btn = tk.Button(right_tool_frame, text="지우개", command=use_eraser)
eraser_btn.pack(side="left", padx=5)

# ▶ 캔버스 (그림판 본체)
canvas = tk.Canvas(root, bg="white", width=800, height=600)
canvas.pack(fill="both", expand=True)

# 마우스 이벤트 바인딩
canvas.bind("<Button-1>", start_draw)        # 그리기 시작
canvas.bind("<B1-Motion>", draw)             # 마우스 이동 중 그리기
canvas.bind("<ButtonRelease-1>", end_draw)   # 그리기 종료

root.mainloop()

 

✔ 설명 요약  

- 지우개는 그냥 "배경색(white)으로 선을 그리는 것"입니다.
- 지우개 굵기 = 브러시 굵기와 동일한 슬라이더로 조절됩니다.
- `Ctrl + Z` 입력 시 가장 마지막 선을 삭제하여 **실행 취소** 구현
- (참고) 투명하게 지우는 기능은 Tkinter 기본 canvas로는 불가능합니다.

 

 ✔ 결과 화면