Tkinter OptionMenu 튜토리얼
Tkinter OptionMenu로 드롭다운을 만드는 방법을 배워보세요. 콜백, 라이브 업데이트, 옵션 추가/제거, 스타일링 팁, 그리고 완전 실행 가능한 예제를 다룹니다.
튜토리얼 진행률
1 Tkinter OptionMenu 소개
Tkinter의 OptionMenu는 변수에 연결된 드롭다운 목록을 생성합니다. 테마, 언어 또는 유한한 옵션 집합과 같은 선택에 유용합니다. 내부적으로 선택된 값을 변수에 저장하고 사용자가 새 항목을 선택할 때마다 함수를 호출할 수 있습니다.
이 가이드가 끝나면 미리보기 창을 업데이트하고 선택한 테마와 함께 메시지를 표시하는 실행 가능한 테마 선택기 앱을 갖게 될 것입니다.
2 사전 요구 사항: Python 및 Tkinter
Python 3.7 이상이 필요합니다. Tkinter는 macOS 및 Windows의 대부분의 Python 설치에 포함되어 있습니다. Linux를 사용하는 경우 tk 패키지를 설치하세요:
# Debian/Ubuntu
sudo apt-get install python3-tk
Tkinter가 사용 가능한지 확인하세요:
python -m tkinter
작은 창이 열리면 Tkinter가 작동하는 것입니다.
3 최소 OptionMenu: 핵심 구성 요소
세 가지 구성 요소가 필요합니다. Tkinter 변수(보통 StringVar), 옵션 목록 및 변수에 연결된 OptionMenu입니다.
import tkinter as tk
root = tk.Tk()
root.title("최소 OptionMenu")
# 1) 현재 선택을 저장하는 변수
choice = tk.StringVar(value="A")
# 2) OptionMenu를 생성하고 변수와 옵션을 전달합니다
menu = tk.OptionMenu(root, choice, "A", "B", "C")
menu.pack(padx=20, pady=20)
root.mainloop()
- StringVar는 현재 값을 드롭다운과 동기화합니다.
value="A"는 기본값을 설정합니다. 없으면 일반적으로 첫 번째 옵션이 선택됩니다.choice.set("B")를 업데이트하면 OptionMenu 선택이 프로그래밍 방식으로 이동합니다.
4 변경 사항에 반응: 콜백 추가
command 인수에 함수를 전달합니다. Tkinter는 새로 선택된 값을 사용하여 이 함수를 호출합니다.
import tkinter as tk
from tkinter import messagebox
def on_select(value):
messagebox.showinfo("선택", f"선택하신 항목: {value}")
root = tk.Tk()
choice = tk.StringVar(value="Ocean")
menu = tk.OptionMenu(root, choice, "Ocean", "Forest", "Sunset", command=on_select)
menu.pack(padx=20, pady=20)
root.mainloop()
콜백을 사용하여 다른 위젯을 동기화하거나, 유효성을 검사하거나, 정보 패널을 업데이트합니다.
5 실시간 미리보기 구축 (예제처럼)
테마 데이터를 저장한 다음 선택이 변경될 때마다 미리보기 창을 업데이트합니다.
import tkinter as tk
from tkinter import messagebox
themes = {
"Ocean": {"primary": "#1a73e8", "secondary": "#4285f4", "text": "white"},
"Forest": {"primary": "#2e7d32", "secondary": "#4caf50", "text": "white"},
"Sunset": {"primary": "#d32f2f", "secondary": "#f44336", "text": "white"},
}
def update_preview(theme_name):
t = themes[theme_name]
preview.configure(bg=t["primary"])
title.configure(bg=t["primary"], fg=t["text"])
button.configure(bg=t["secondary"], fg=t["text"], activebackground=t["primary"], activeforeground=t["text"])
root = tk.Tk()
choice = tk.StringVar(value="Ocean")
menu = tk.OptionMenu(root, choice, *themes.keys(), command=lambda v: update_preview(v))
menu.pack(padx=20, pady=10)
preview = tk.Frame(root, width=220, height=120, relief="raised", bd=2)
preview.pack(pady=10)
title = tk.Label(preview, text="테마 미리보기")
title.pack(pady=6)
button = tk.Button(preview, text="확인", command=lambda: messagebox.showinfo("테마", f"{choice.get()}"))
button.pack(pady=6)
update_preview(choice.get())
root.mainloop()
6 옵션 변경 및 항목 비활성화
OptionMenu에는 내장된 제거/추가 API가 없습니다. 일반적인 접근 방식은 업데이트된 옵션으로 메뉴를 다시 빌드하고 현재 선택을 유지하는 것입니다.
def rebuild_options(new_options, keep_value=True):
current = choice.get() if keep_value else new_options[0]
menu["menu"].delete(0, "end")
for opt in new_options:
menu["menu"].add_command(label=opt, command=lambda v=opt: choice.set(v))
choice.set(current)
# 이 항목들로 시작
choices = ["A", "B", "C"]
choice = tk.StringVar(value="B")
menu = tk.OptionMenu(root, choice, *choices)
menu.pack(padx=20, pady=20)
# 나중에 "B"를 제거
rebuild_options([opt for opt in choices if opt != "B"])
특정 항목을 비활성화하려면 캐스케이드 하위 메뉴로 묶고 state="disabled"를 사용하세요. 제거 또는 재정렬은 다시 빌드하면 더 간단합니다.
7 스타일링 및 레이아웃: 모양 다듬기
configure(width=...)를 사용하여 너비를 제어합니다. 글꼴 및 색상의 경우 메뉴 및 내부 메뉴 위젯에서 속성을 설정합니다. ttk.Frame과 tk.OptionMenu를 결합하면 간격을 깔끔하게 할 수 있습니다.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
frame = ttk.Frame(root, padding=16)
frame.pack()
choice = tk.StringVar(value="Ocean")
menu = tk.OptionMenu(frame, choice, "Ocean", "Forest", "Sunset")
menu.configure(width=14, font=("Helvetica", 11))
menu["menu"].configure(font=("Helvetica", 11))
ttk.Label(frame, text="테마를 선택하세요:").pack(anchor="w", pady=(0, 6))
menu.pack(anchor="w")
root.mainloop()
8 일반적인 함정 및 주의사항
- 초기 값을 설정하지 않으면 선택이 비어 있게 됩니다.
- 콜백은 변수가 아닌 새 값을 받습니다. 더 넓은 상태가 필요한 경우 변수를 사용하세요.
- OptionMenu에는 직접적인 "옵션 제거" API가 없습니다. 내부
menu위젯을 통해 다시 빌드하세요. tk와ttk를 혼용하면 미묘한 스타일 차이가 발생할 수 있습니다.- 일부 시스템에서는 플랫폼 렌더링으로 인해 내부 메뉴의 글꼴 변경이 적용되지 않습니다.
9 연습: 옵션 추가 및 제거
최소 예제를 확장하세요: 입력 필드와 입력된 옵션을 메뉴에 삽입하는 버튼(없는 경우)을 추가하고 선택합니다. 그런 다음 현재 선택된 옵션을 제거하는 다른 버튼을 추가합니다.
import tkinter as tk
root = tk.Tk()
choice = tk.StringVar(value="A")
options = ["A", "B", "C"]
menu = tk.OptionMenu(root, choice, *options)
menu.pack(padx=16, pady=16)
entry = tk.Entry(root)
entry.pack(padx=16)
def add_option():
val = entry.get().strip()
if not val or val in options:
return
options.append(val)
menu["menu"].add_command(label=val, command=lambda v=val: choice.set(v))
choice.set(val)
def remove_selected():
val = choice.get()
if val not in options:
return
options.remove(val)
rebuild_options()
tk.Button(root, text="추가", command=add_option).pack(pady=6)
tk.Button(root, text="선택 항목 제거", command=remove_selected).pack(pady=6)
def rebuild_options():
current = choice.get()
menu["menu"].delete(0, "end")
for opt in options:
menu["menu"].add_command(label=opt, command=lambda v=opt: choice.set(v))
if options:
choice.set(current if current in options else options[0])
root.mainloop()
10 전체 프로젝트: 미리보기 포함 테마 선택기
이 코드를 theme_selector.py라는 파일에 복사하고 python theme_selector.py로 실행하세요.
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
class ColorThemeSelector(tk.Tk):
def __init__(self):
super().__init__()
# 메인 창 구성
self.title("OptionMenu 예제")
self.geometry("400x300")
self.configure(padx=20, pady=20)
# 색상 테마 정의
self.color_themes = {
"Ocean": {"primary": "#1a73e8", "secondary": "#4285f4", "text": "white"},
"Forest": {"primary": "#2e7d32", "secondary": "#4caf50", "text": "white"},
"Sunset": {"primary": "#d32f2f", "secondary": "#f44336", "text": "white"},
"Lavender": {"primary": "#7b1fa2", "secondary": "#9c27b0", "text": "white"}
}
# 프레임 생성 및 구성
self.main_frame = ttk.Frame(self)
self.main_frame.pack(expand=True, fill='both')
# 선택된 옵션을 저장할 StringVar 생성
self.selected_theme = tk.StringVar()
self.selected_theme.set("Ocean") # 기본값 설정
# 레이블 생성
self.label = ttk.Label(
self.main_frame,
text="컬러 테마를 선택하세요:",
font=('Helvetica', 12)
)
self.label.pack(pady=10)
# OptionMenu 생성
self.theme_menu = tk.OptionMenu(
self.main_frame,
self.selected_theme,
*self.color_themes.keys(),
command=self.update_preview
)
self.theme_menu.configure(width=15)
self.theme_menu.pack(pady=10)
# 미리보기 프레임 생성
self.preview_frame = tk.Frame(
self.main_frame,
width=200,
height=100,
relief="raised",
bd=2
)
self.preview_frame.pack(pady=20)
# 미리보기 요소 생성
self.preview_title = tk.Label(
self.preview_frame,
text="테마 미리보기",
font=('Helvetica', 10)
)
self.preview_title.pack(pady=5)
self.preview_button = tk.Button(
self.preview_frame,
text="샘플 버튼",
command=self.show_selection
)
self.preview_button.pack(pady=10)
# 미리보기 초기화
self.update_preview()
def update_preview(self, *args):
"""선택한 테마 색상으로 미리보기 프레임 업데이트"""
theme = self.color_themes[self.selected_theme.get()]
# 미리보기 프레임 배경 업데이트
self.preview_frame.configure(bg=theme["primary"])
self.preview_title.configure(
bg=theme["primary"],
fg=theme["text"]
)
self.preview_button.configure(
bg=theme["secondary"],
fg=theme["text"],
activebackground=theme["primary"],
activeforeground=theme["text"]
)
def show_selection(self):
"""현재 선택 사항이 포함된 메시지 상자 표시"""
messagebox.showinfo(
"선택한 테마",
f"'{self.selected_theme.get()}' 테마를 선택했습니다!"
)
if __name__ == "__main__":
app = ColorThemeSelector()
app.mainloop()
실행: python theme_selector.py. 테마를 변경해 보세요. 미리보기가 실시간으로 업데이트되는 것을 확인하세요.