Python Tkinter - 2. 레이아웃 관리와 고급 이벤트 처리

2025. 1. 20. 00:19프로그래밍 언어/Python

이론

레이아웃 관리자

Tkinter에서 위젯을 배치하기 위해 다양한 레이아웃 관리자를 제공합니다. 이 관리자를 통해 사용자 인터페이스(UI)를 체계적으로 설계할 수 있습니다.

1. pack: 위젯을 상하좌우로 배치

  • 장점: 간단하고 빠르게 레이아웃을 설정할 수 있음.
  • 단점: 복잡한 레이아웃에는 적합하지 않으며, 세밀한 제어가 어려움.
  • 가장 간단한 레이아웃 관리 방식.
  • 위젯을 한 방향(위, 아래, 왼쪽, 오른쪽)으로 배치하며, 순서대로 쌓입니다.

예제:

import tkinter as tk

root = tk.Tk()

label1 = tk.Label(root, text="위쪽")
label1.pack(side="top")

label2 = tk.Label(root, text="아래쪽")
label2.pack(side="bottom")

root.mainloop()

2. grid: 행과 열을 기반으로 정렬

  • 장점: 행과 열을 사용해 직관적으로 배치 가능, 복잡한 레이아웃에 적합.
  • 단점: 코드가 길어질 수 있으며, 다른 레이아웃 관리자와 혼합 사용 시 어려움이 있을 수 있음.
  • 위젯을 격자 형태로 배치합니다.
  • 행(row)과 열(column)을 지정하여 위치를 설정합니다.

예제:

label1 = tk.Label(root, text="첫 번째 행, 첫 번째 열")
label1.grid(row=0, column=0)

label2 = tk.Label(root, text="첫 번째 행, 두 번째 열")
label2.grid(row=0, column=1)

label3 = tk.Label(root, text="두 번째 행, 첫 번째 열")
label3.grid(row=1, column=0)

3. place: 절대 좌표를 사용한 세밀한 위치 조정

  • 장점: 픽셀 단위로 정확한 위치 설정 가능.
  • 단점: 창 크기가 변경되면 레이아웃이 깨질 수 있어 유지보수가 어려움.
  • 위젯을 픽셀 단위로 정확하게 배치합니다.
  • x와 y 좌표를 사용하여 위치를 설정합니다.

예제:

label = tk.Label(root, text="정확한 위치 지정")
label.place(x=50, y=100)

고급 이벤트 처리

1. bind 메서드: 특정 키보드 및 마우스 이벤트 처리

  • 주의사항: Tkinter는 이벤트를 처리할 때 메인 루프를 차단하지 않도록 설계되어야 합니다. 비동기 작업은 별도의 스레드나 after 메서드를 사용해야 합니다.
  • 사용자가 특정 키를 누르거나 마우스를 클릭했을 때 이벤트를 처리합니다.
  • 이벤트 이름(<Button-1>, <Key> 등)을 지정하여 동작을 연결합니다.

예제:

def on_key(event):
    print(f"키 입력: {event.char}")

def on_click(event):
    print(f"마우스 클릭 위치: ({event.x}, {event.y})")

root.bind("<Key>", on_key)
root.bind("<Button-1>", on_click)

2. 이벤트 객체: 동적 상호작용 구현

  • 이벤트 객체를 통해 추가 정보를 얻을 수 있습니다.
    • 키보드 입력: event.char
    • 마우스 위치: event.x, event.y

실습

1. 다양한 레이아웃 설계

pack과 grid 혼합:

label1 = tk.Label(root, text="위쪽")
label1.pack(side="top")

frame = tk.Frame(root)
frame.pack()

label2 = tk.Label(frame, text="첫 번째 행, 첫 번째 열")
label2.grid(row=0, column=0)

label3 = tk.Label(frame, text="첫 번째 행, 두 번째 열")
label3.grid(row=0, column=1)

동적으로 크기 조정:

label = tk.Label(root, text="창 크기를 조정해 보세요", bg="lightblue")
label.pack(fill="both", expand=True)

2. 키보드 및 마우스 이벤트 처리

키 입력에 따라 Label 변경:

def change_text(event):
    label.config(text=f"입력된 키: {event.char}")

label = tk.Label(root, text="키를 입력하세요")
label.pack()

root.bind("<Key>", change_text)

마우스 클릭 위치를 캔버스에 표시:

def draw_circle(event):
    canvas.create_oval(event.x-5, event.y-5, event.x+5, event.y+5, fill="red")

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

canvas.bind("<Button-1>", draw_circle)

동적 위젯 추가 및 제거:

def add_label():
    new_label = tk.Label(root, text="새로운 레이블")
    new_label.pack()
    labels.append(new_label)

def remove_label():
    if labels:
        label = labels.pop()
        label.destroy()

labels = []

add_button = tk.Button(root, text="추가", command=add_label)
add_button.pack()

remove_button = tk.Button(root, text="제거", command=remove_label)
remove_button.pack()

과제

할 일 목록 관리 프로그램

요구사항

  1. 작업을 추가하고 목록에 표시.
  2. 작업을 삭제.
  3. 키보드 단축키를 활용해 작업 관리.

예제 구현

def add_task():
    task = entry.get()
    if task:
        tasks.append(task)
        listbox.insert(tk.END, task)
        entry.delete(0, tk.END)

def delete_task():
    selected = listbox.curselection()
    if selected:
        tasks.pop(selected[0])
        listbox.delete(selected[0])

def clear_all(event):
    listbox.delete(0, tk.END)
    tasks.clear()

root.bind("<Control-c>", clear_all)

tasks = []

entry = tk.Entry(root)
entry.pack()

add_button = tk.Button(root, text="추가", command=add_task)
add_button.pack()

delete_button = tk.Button(root, text="삭제", command=delete_task)
delete_button.pack()

listbox = tk.Listbox(root)
listbox.pack()

root.mainloop()

기대 효과

  • 레이아웃 관리 방법을 익혀 다양한 UI를 설계할 수 있습니다.
  • 고급 이벤트 처리 기법을 사용하여 동적인 애플리케이션을 제작할 수 있습니다.