Python에서 GUI를 만들 때 tkinter는 가장 기본적이고 널리 쓰이는 라이브러리입니다. 윈도우, 버튼, 라벨 등 다양한 위젯을 손쉽게 구현할 수 있으며, 학습 곡선이 완만해 초보자에게 적합합니다.
🖥️ Tkinter 기본 개념
- Tkinter: Python 표준 GUI 라이브러리, 별도 설치 없이 사용 가능.
- 윈도우 생성: Tk() 객체를 만들어 기본 창을 띄움.
- 이벤트 루프: mainloop()를 호출해 창을 유지하고 이벤트 처리.
python
import tkinter as tk
root = tk.Tk() # 기본 윈도우 생성
root.title("Hello Tkinter") # 창 제목 설정
root.geometry("300x200") # 창 크기 설정
label = tk.Label(root, text="안녕하세요!") # 라벨 추가
label.pack()
root.mainloop() # 이벤트 루프 실행
🔑 주요 위젯
- Label: 텍스트 표시
- Button: 클릭 이벤트 처리
- Entry: 사용자 입력 필드
- Text: 여러 줄 입력
- Frame: 위젯 그룹화
- Canvas: 도형, 이미지 그리기
- ttk: 현대적 테마 위젯 제공 (콤보박스, 트리뷰 등)
📐 레이아웃 관리
- pack: 위젯을 위/아래/좌/우로 배치
- grid: 행과 열 기반 배치
- place: 절대 좌표 배치
⚡ 이벤트와 바인딩
- command 옵션: 버튼 클릭 시 함수 실행
- bind 메서드: 키보드/마우스 이벤트 연결
python
def on_click():
print("버튼 클릭!")
btn = tk.Button(root, text="클릭", command=on_click)
btn.pack()
🗂️ 프로젝트 예제: 간단한 할 일 관리 앱 (To-Do List)
Tkinter로 가장 많이 만드는 실무형 예제 중 하나가 작업 관리 도구입니다. 이 앱을 통해 입력, 저장, 삭제, 레이아웃, 이벤트 처리까지 모두 경험할 수 있습니다.
1. 기본 구조
- 윈도우 생성: Tk()로 메인 창 생성
- Frame: 입력 영역과 리스트 영역을 구분
- Entry: 새로운 할 일을 입력
- Listbox: 할 일 목록 표시
- Button: 추가/삭제 기능 구현
python
import tkinter as tk
def add_task():
task = entry.get()
if task:
listbox.insert(tk.END, task)
entry.delete(0, tk.END)
def delete_task():
selected = listbox.curselection()
if selected:
listbox.delete(selected[0])
root = tk.Tk()
root.title("할 일 관리 앱")
root.geometry("400x300")
frame = tk.Frame(root)
frame.pack(pady=10)
entry = tk.Entry(frame, width=30)
entry.pack(side=tk.LEFT, padx=5)
add_btn = tk.Button(frame, text="추가", command=add_task)
add_btn.pack(side=tk.LEFT)
delete_btn = tk.Button(root, text="삭제", command=delete_task)
delete_btn.pack(pady=5)
listbox = tk.Listbox(root, width=40, height=10)
listbox.pack(pady=10)
root.mainloop()
📊 실무형 확장 아이디어
이제 단순한 예제를 실무형 프로젝트로 발전시켜 봅시다.
- 파일 저장/불러오기 → open(), write()로 할 일 목록을 텍스트 파일에 저장하고 다시 불러오기
- 체크박스 상태 관리 → 완료된 작업을 체크 표시로 관리
- 날짜/시간 추가 → datetime 모듈과 함께 마감일 표시
- 메뉴바 추가 → "파일 → 저장/불러오기" 메뉴 구성
- ttk.Treeview → 프로젝트별로 작업을 계층 구조로 관리
🛠️ 학습 포인트
- 레이아웃 관리: pack, grid, place를 상황에 맞게 활용
- 이벤트 처리: 키보드 단축키(Ctrl+S 저장 등) 바인딩
- 모듈화: 기능별로 함수/클래스로 분리
- 실무 적용: 간단한 업무 관리, 데이터 입력 툴, 보고서 생성 UI 등에 활용 가능
🛠️ 기본 윈도우와 위젯 생성
- Tkinter 윈도우 생성: Tk()로 메인 창 만들기
- Entry: 할 일을 입력하는 필드
- Listbox: 입력된 할 일을 표시하는 목록
- Button: "추가"와 "삭제" 기능 구현
🛠️ 기능 구현 (추가/삭제)
- command 옵션을 사용해 버튼 클릭 시 함수 실행
- add_task() → Entry에서 입력받아 Listbox에 추가
- delete_task() → 선택된 항목을 삭제
🛠️ 파일 저장/불러오기 기능
- 파일 입출력을 통해 실무형 확장
- with open("tasks.txt", "w") → 현재 목록 저장
- with open("tasks.txt", "r") → 프로그램 실행 시 불러오기
🛠️ 체크박스와 상태 관리
- Checkbutton을 활용해 완료 여부 표시
- 완료된 작업은 ✔ 표시 또는 색상 변경
🛠️ 고급 UI 구성
- Menu: "파일 → 저장/불러오기" 메뉴 추가
- Treeview: 프로젝트별 작업을 계층 구조로 관리
- 레이아웃 관리: pack, grid, place를 적절히 혼합
🛠️ 실무 적용 사례
- 업무 관리 툴: 팀별 작업 관리
- 데이터 입력 앱: 보고서 작성용 입력 UI
- 간단 CRM: 고객 정보 관리
👉 Tkinter는 대규모 앱보다는 작은 업무 자동화 도구에 적합합니다.
📂 파일 저장/불러오기 기능 추가
이 버전은 사용자가 입력한 할 일을 텍스트 파일에 저장하고, 프로그램 실행 시 불러올 수 있도록 합니다.
python
import tkinter as tk
def add_task():
task = entry.get()
if task:
listbox.insert(tk.END, task)
entry.delete(0, tk.END)
def delete_task():
selected = listbox.curselection()
if selected:
listbox.delete(selected[0])
def save_tasks():
tasks = listbox.get(0, tk.END)
with open("tasks.txt", "w", encoding="utf-8") as f:
for task in tasks:
f.write(task + "\n")
def load_tasks():
try:
with open("tasks.txt", "r", encoding="utf-8") as f:
for line in f:
listbox.insert(tk.END, line.strip())
except FileNotFoundError:
pass
root = tk.Tk()
root.title("할 일 관리 앱")
root.geometry("400x300")
frame = tk.Frame(root)
frame.pack(pady=10)
entry = tk.Entry(frame, width=30)
entry.pack(side=tk.LEFT, padx=5)
add_btn = tk.Button(frame, text="추가", command=add_task)
add_btn.pack(side=tk.LEFT)
delete_btn = tk.Button(root, text="삭제", command=delete_task)
delete_btn.pack(pady=5)
save_btn = tk.Button(root, text="저장", command=save_tasks)
save_btn.pack(pady=5)
listbox = tk.Listbox(root, width=40, height=10)
listbox.pack(pady=10)
load_tasks() # 실행 시 기존 데이터 불러오기
root.mainloop()
🌳 Treeview를 활용한 고급 UI
ttk.Treeview를 사용하면 프로젝트별로 작업을 계층 구조로 관리할 수 있습니다.
python
import tkinter as tk
from tkinter import ttk
def add_task():
project = project_entry.get()
task = task_entry.get()
if project and task:
if project not in project_nodes:
node = tree.insert("", tk.END, text=project)
project_nodes[project] = node
tree.insert(project_nodes[project], tk.END, text=task)
task_entry.delete(0, tk.END)
root = tk.Tk()
root.title("프로젝트별 할 일 관리")
root.geometry("500x400")
project_nodes = {}
frame = tk.Frame(root)
frame.pack(pady=10)
project_entry = tk.Entry(frame, width=20)
project_entry.pack(side=tk.LEFT, padx=5)
project_entry.insert(0, "프로젝트명")
task_entry = tk.Entry(frame, width=30)
task_entry.pack(side=tk.LEFT, padx=5)
task_entry.insert(0, "할 일")
add_btn = tk.Button(frame, text="추가", command=add_task)
add_btn.pack(side=tk.LEFT)
tree = ttk.Treeview(root)
tree.pack(fill=tk.BOTH, expand=True)
root.mainloop()
✅ 전체 샘플 소스
python
import tkinter as tk
from tkinter import ttk
project_nodes = {}
def add_task():
project = project_entry.get().strip()
task = task_entry.get().strip()
if project and task:
if project not in project_nodes:
node = tree.insert("", tk.END, text=project, values=(""))
project_nodes[project] = node
tree.insert(project_nodes[project], tk.END, text=task, values=("미완료"))
task_entry.delete(0, tk.END)
def toggle_status():
selected = tree.selection()
for item in selected:
current_status = tree.set(item, "status")
new_status = "완료" if current_status == "미완료" else "미완료"
tree.set(item, "status", new_status)
def save_tasks():
with open("tasks_tree_status.txt", "w", encoding="utf-8") as f:
for project, node in project_nodes.items():
f.write(f"[{project}]\n")
children = tree.get_children(node)
for child in children:
task = tree.item(child, "text")
status = tree.set(child, "status")
f.write(f"{task}|{status}\n")
def load_tasks():
try:
with open("tasks_tree_status.txt", "r", encoding="utf-8") as f:
current_project = None
for line in f:
line = line.strip()
if line.startswith("[") and line.endswith("]"):
project = line[1:-1]
node = tree.insert("", tk.END, text=project, values=(""))
project_nodes[project] = node
current_project = project
elif current_project:
if "|" in line:
task, status = line.split("|")
tree.insert(project_nodes[current_project], tk.END, text=task, values=(status))
except FileNotFoundError:
pass
root = tk.Tk()
root.title("프로젝트별 할 일 관리 앱 (체크박스 상태 포함)")
root.geometry("650x400")
frame = tk.Frame(root)
frame.pack(pady=10)
project_entry = tk.Entry(frame, width=20)
project_entry.pack(side=tk.LEFT, padx=5)
project_entry.insert(0, "프로젝트명")
task_entry = tk.Entry(frame, width=30)
task_entry.pack(side=tk.LEFT, padx=5)
task_entry.insert(0, "할 일")
add_btn = tk.Button(frame, text="추가", command=add_task)
add_btn.pack(side=tk.LEFT)
toggle_btn = tk.Button(root, text="상태 토글", command=toggle_status)
toggle_btn.pack(pady=5)
save_btn = tk.Button(root, text="저장", command=save_tasks)
save_btn.pack(pady=5)
tree = ttk.Treeview(root, columns=("status"), show="tree headings")
tree.heading("#0", text="작업")
tree.heading("status", text="상태")
tree.pack(fill=tk.BOTH, expand=True)
load_tasks()
root.mainloop()
'Python' 카테고리의 다른 글
| 윈도우 서버(또는 PC)에 대한 무차별 대입 공격(Brute-force)을 방어 Python 소스 (0) | 2026.05.13 |
|---|---|
| Uvicorn ASGI(Asynchronous Server Gateway Interface) 서버 사용방법 (0) | 2026.05.13 |
| Pillow(PIL Fork) 이미지 처리 라이브러리 사용법 (0) | 2026.05.11 |
| Python으로 유튜브 및 다양한 사이트의 영상·오디오를 다운로드하고 변환 (3) | 2026.05.08 |
| Python을 실행파일로 만드는 방법 (0) | 2026.05.08 |