Ver3.0 ๐จ ํ์ด์ฌ GUI ํ๋ก๊ทธ๋๋ฐ: Tkinter ์ฌ์ฉ๋ฒ

๐จ ํ์ด์ฌ GUI ํ๋ก๊ทธ๋๋ฐ: Tkinter ์ฌ์ฉ๋ฒ
์น๊ตฌ์ฒ๋ผ ์ฝ๊ณ ์ฌ๋ฏธ์๊ฒ ๋ฐฐ์ฐ๋ GUI ํ๋ก๊ทธ๋๋ฐ์ ์ธ๊ณ! ๐
์๋ ! ๐ ์ค๋์ ํ์ด์ฌ์ผ๋ก ๋ฉ์ง ์ฐฝ(์๋์ฐ)์ ๋ง๋ค์ด๋ณด๋ ์๊ฐ์ด์ผ. ์ปค๋งจ๋ ๋ผ์ธ์์ ๋ฒ์ด๋ ๋ฒํผ๋ ๋๋ฅด๊ณ , ํ ์คํธ๋ ์ ๋ ฅ๋ฐ๊ณ , ์ด๋ฏธ์ง๋ ๋ณด์ฌ์ฃผ๋ ๊ทธ๋ฐ ํ๋ก๊ทธ๋จ ๋ง์ด์ผ. ๋ฐ๋ก **Tkinter**๋ฅผ ์ฌ์ฉํด์!
Tkinter๋ ํ์ด์ฌ์ ๊ธฐ๋ณธ์ผ๋ก ๋ด์ฅ๋์ด ์์ด์ ๋ณ๋ ์ค์น ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ GUI ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ๐ ์ฒ์ GUI ํ๋ก๊ทธ๋๋ฐ์ ๋ฐฐ์ฐ๋ ์ฌ๋๋ค์๊ฒ ์ ๋ง ์ข์ ์ ํ์ด์ง. ๋ณต์กํ์ง ์์ผ๋ฉด์๋ ์ค์ฉ์ ์ธ ํ๋ก๊ทธ๋จ์ ์ถฉ๋ถํ ๋ง๋ค ์ ์๊ฑฐ๋ !
๐ Tkinter๊ฐ ๋ญ๊ธธ๋?
Tkinter๋ **Tk interface**์ ์ค์๋ง์ด์ผ. Tk๋ ์๋ Tcl์ด๋ผ๋ ์คํฌ๋ฆฝํ ์ธ์ด์ฉ์ผ๋ก ๋ง๋ค์ด์ง GUI ํดํท์ธ๋ฐ, ํ์ด์ฌ์์๋ ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋ ๊ฒ ๋ฐ๋ก Tkinter์ง! ๐ฆ
๐ก Tkinter์ ์ฅ์
โ
ํ์ด์ฌ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ (๋ณ๋ ์ค์น ๋ถํ์)
โ
ํฌ๋ก์ค ํ๋ซํผ ์ง์ (Windows, macOS, Linux ๋ชจ๋ OK)
โ
๋ฐฐ์ฐ๊ธฐ ์ฌ์ด ๋ฌธ๋ฒ๊ณผ ๊ตฌ์กฐ
โ
๊ฐ๋ณ๊ณ ๋น ๋ฅธ ์คํ ์๋
โ
ํ๋ถํ ์์ ฏ(๋ฒํผ, ๋ ์ด๋ธ, ์
๋ ฅ์ฐฝ ๋ฑ) ์ ๊ณต
๋ฌผ๋ก ์ต์ ํธ๋ ๋ํ ๋์์ธ์ ์ํ๋ค๋ฉด PyQt๋ Kivy ๊ฐ์ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ด. ํ์ง๋ง ๊ฐ๋จํ ๋๊ตฌ๋ ์ ํธ๋ฆฌํฐ๋ฅผ ๋ง๋ค ๋๋ Tkinter๊ฐ ์ ๋ง ์ต๊ณ ์ผ! ๐
๐ ์ฒซ ๋ฒ์งธ Tkinter ํ๋ก๊ทธ๋จ ๋ง๋ค๊ธฐ
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํด๋ณผ๊น? ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์ฐฝ์ ๋์ฐ๋ ๊ฒ๋ถํฐ ์์ํด๋ณด์!
import tkinter as tk
# ๋ฉ์ธ ์๋์ฐ ์์ฑ
root = tk.Tk()
root.title("๋์ ์ฒซ GUI ํ๋ก๊ทธ๋จ")
root.geometry("400x300")
# ํ๋ก๊ทธ๋จ ์คํ
root.mainloop()
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด 400x300 ํฌ๊ธฐ์ ๋น ์ฐฝ์ด ํ๋ ๋ฌ๋ค! ๐ ๊ฐ๋จํ์ง? ํ๋์ฉ ๋ฏ์ด๋ณด์.
๐ ์ฝ๋ ๋ถ์
import tkinter as tk
Tkinter ๋ชจ๋์ ๋ถ๋ฌ์ค๋ ๊ฑฐ์ผ. ๋ณดํต tk๋ผ๋ ์งง์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํด. ํ์ดํ์ด ํธํ๊ฑฐ๋ !
root = tk.Tk()
๋ฉ์ธ ์๋์ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ถ๋ถ์ด์ผ. ๋ชจ๋ GUI ์์๋ค์ ๋ถ๋ชจ๊ฐ ๋๋ ์ต์์ ์ฐฝ์ด์ง. ๋ณดํต root๋ window๋ผ๋ ์ด๋ฆ์ ๋ง์ด ์จ.
root.title("...")
์ฐฝ์ ์ ๋ชฉ์ ์ค์ ํ๋ ๋ฉ์๋์ผ. ์ฐฝ ์๋จ์ ํ์๋๋ ๊ทธ ํ
์คํธ!
root.geometry("400x300")
์ฐฝ์ ํฌ๊ธฐ๋ฅผ ์ค์ ํด. "๊ฐ๋กx์ธ๋ก" ํ์์ผ๋ก ํฝ์
๋จ์๋ก ์ง์ ํ๋ฉด ๋ผ.
root.mainloop()
์ด๊ฒ ์ ๋ง ์ค์ํด! ์ด ๋ฉ์๋๊ฐ ํธ์ถ๋์ด์ผ ์ฐฝ์ด ํ๋ฉด์ ํ์๋๊ณ , ์ฌ์ฉ์์ ์
๋ ฅ์ ๊ธฐ๋ค๋ฆฌ๋ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์์๋ผ. ์ด๊ฒ ์์ผ๋ฉด ์ฐฝ์ด ์์๊ฐ์ ์ฌ๋ผ์ ธ๋ฒ๋ ค! ๐ฑ
๐จ ์์ ฏ(Widget) ์ถ๊ฐํ๊ธฐ
๋น ์ฐฝ๋ง ์์ผ๋ฉด ๋ญํด? ์ด์ ๋ฒํผ, ๋ ์ด๋ธ, ์ ๋ ฅ์ฐฝ ๊ฐ์ ๊ฒ๋ค์ ์ถ๊ฐํด๋ณด์! ์ด๋ฐ GUI ์์๋ค์ **์์ ฏ(Widget)**์ด๋ผ๊ณ ๋ถ๋ฌ. ๐งฉ
๐ Label - ํ ์คํธ ํ์ํ๊ธฐ
Label์ ํ๋ฉด์ ํ ์คํธ๋ ์ด๋ฏธ์ง๋ฅผ ํ์ํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์์ ฏ์ด์ผ.
import tkinter as tk
root = tk.Tk()
root.title("Label ์์ ")
root.geometry("400x300")
# Label ์์ฑ
label = tk.Label(root, text="์๋
ํ์ธ์! ๐", font=("Arial", 20))
label.pack(pady=20)
root.mainloop()
pack() ๋ฉ์๋๋ ์์ ฏ์ ์ฐฝ์ ๋ฐฐ์นํ๋ ๋ฐฉ๋ฒ ์ค ํ๋์ผ. pady=20์ ์์๋๋ก 20ํฝ์
์ ์ฌ๋ฐฑ์ ์ค๋ค๋ ๋ป์ด์ง!
๐ Button - ํด๋ฆญํ ์ ์๋ ๋ฒํผ
๋ฒํผ์ ์ฌ์ฉ์๊ฐ ํด๋ฆญํด์ ์ด๋ค ๋์์ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ์์ ฏ์ด์ผ.
import tkinter as tk
def button_click():
print("๋ฒํผ์ด ํด๋ฆญ๋์์ต๋๋ค!")
label.config(text="๋ฒํผ์ ๋๋ ์ด์! ๐")
root = tk.Tk()
root.title("Button ์์ ")
root.geometry("400x300")
label = tk.Label(root, text="๋ฒํผ์ ๋๋ฌ๋ณด์ธ์", font=("Arial", 16))
label.pack(pady=20)
button = tk.Button(root, text="ํด๋ฆญ!", command=button_click,
bg="#7c9cbf", fg="white", font=("Arial", 14))
button.pack()
root.mainloop()
๐ก ํต์ฌ ํฌ์ธํธ
command ๋งค๊ฐ๋ณ์์ ํจ์๋ฅผ ์ง์ ํ๋ฉด, ๋ฒํผ์ ํด๋ฆญํ์ ๋ ๊ทธ ํจ์๊ฐ ์คํ๋ผ! ์ฃผ์ํ ์ ์ ํจ์ ์ด๋ฆ๋ง ์ฐ๊ณ ๊ดํธ ()๋ ๋ถ์ด์ง ์๋๋ค๋ ๊ฑฐ์ผ. command=button_click()์ด ์๋๋ผ command=button_click์ผ๋ก ์จ์ผ ํด!
โ๏ธ Entry - ํ ์คํธ ์ ๋ ฅ๋ฐ๊ธฐ
Entry๋ ์ฌ์ฉ์๋ก๋ถํฐ ํ ์ค์ ํ ์คํธ๋ฅผ ์ ๋ ฅ๋ฐ์ ์ ์๋ ์์ ฏ์ด์ผ.
import tkinter as tk
def show_input():
user_text = entry.get()
label.config(text=f"์
๋ ฅํ ๋ด์ฉ: {user_text}")
root = tk.Tk()
root.title("Entry ์์ ")
root.geometry("400x300")
label = tk.Label(root, text="์ด๋ฆ์ ์
๋ ฅํ์ธ์", font=("Arial", 14))
label.pack(pady=10)
entry = tk.Entry(root, width=30, font=("Arial", 12))
entry.pack(pady=10)
button = tk.Button(root, text="ํ์ธ", command=show_input)
button.pack(pady=10)
root.mainloop()
entry.get() ๋ฉ์๋๋ก ์
๋ ฅ๋ ํ
์คํธ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ด! ๐ฅ
๐ ๋ ์ด์์ ๊ด๋ฆฌ์ (Layout Managers)
์์ ฏ์ ์ฐฝ์ ๋ฐฐ์นํ๋ ๋ฐฉ๋ฒ์๋ ์ธ ๊ฐ์ง๊ฐ ์์ด. ๊ฐ๊ฐ ํน์ง์ด ๋ค๋ฅด๋๊น ์ํฉ์ ๋ง๊ฒ ์ ํํ๋ฉด ๋ผ!
1๏ธโฃ pack() - ์์ฐจ์ ๋ฐฐ์น
๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด์ผ. ์์ ฏ์ ์์์ ์๋๋ก, ๋๋ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก ์์ฐจ์ ์ผ๋ก ๋ฐฐ์นํด.
import tkinter as tk
root = tk.Tk()
root.title("pack() ์์ ")
root.geometry("300x200")
tk.Label(root, text="์ฒซ ๋ฒ์งธ", bg="#7c9cbf", fg="white").pack(fill=tk.X, padx=10, pady=5)
tk.Label(root, text="๋ ๋ฒ์งธ", bg="#66bb6a", fg="white").pack(fill=tk.X, padx=10, pady=5)
tk.Label(root, text="์ธ ๋ฒ์งธ", bg="#ffa726", fg="white").pack(fill=tk.X, padx=10, pady=5)
root.mainloop()
์ฃผ์ ์ต์ ๋ค:
โข side: TOP(๊ธฐ๋ณธ), BOTTOM, LEFT, RIGHT - ๋ฐฐ์น ๋ฐฉํฅ
โข fill: X, Y, BOTH - ๊ณต๊ฐ ์ฑ์ฐ๊ธฐ
โข expand: True/False - ๋จ์ ๊ณต๊ฐ ํ์ฅ
โข padx, pady: ์ธ๋ถ ์ฌ๋ฐฑ
โข ipadx, ipady: ๋ด๋ถ ์ฌ๋ฐฑ
2๏ธโฃ grid() - ๊ฒฉ์ ํํ ๋ฐฐ์น
ํ ํํ๋ก ์์ ฏ์ ๋ฐฐ์นํ ๋ ์ ๋ง ์ ์ฉํด! ํ(row)๊ณผ ์ด(column)์ ์ง์ ํด์ ์ ํํ ์์น์ ๋ฐฐ์นํ ์ ์์ด.
import tkinter as tk
root = tk.Tk()
root.title("grid() ์์ ")
root.geometry("400x300")
# ๊ณ์ฐ๊ธฐ ๋ ์ด์์ ์์
tk.Entry(root, width=30).grid(row=0, column=0, columnspan=4, padx=5, pady=5)
buttons = [
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+'
]
row_val = 1
col_val = 0
for button in buttons:
tk.Button(root, text=button, width=5, height=2).grid(row=row_val, column=col_val, padx=2, pady=2)
col_val += 1
if col_val > 3:
col_val = 0
row_val += 1
root.mainloop()
๐ก grid() ํ
โข columnspan: ์ฌ๋ฌ ์ด์ ์ฐจ์งํ๊ฒ ๋ง๋ค๊ธฐ
โข rowspan: ์ฌ๋ฌ ํ์ ์ฐจ์งํ๊ฒ ๋ง๋ค๊ธฐ
โข sticky: N, S, E, W (๋ถ, ๋จ, ๋, ์) - ์
๋ด์์ ์์ ฏ ์ ๋ ฌ
3๏ธโฃ place() - ์ ๋ ์ขํ ๋ฐฐ์น
์ ํํ x, y ์ขํ๋ฅผ ์ง์ ํด์ ๋ฐฐ์นํ๋ ๋ฐฉ๋ฒ์ด์ผ. ํฝ์ ๋จ์๋ก ์ ๋ฐํ๊ฒ ์ ์ดํ ์ ์์ง๋ง, ์ฐฝ ํฌ๊ธฐ๊ฐ ๋ณํ๋ฉด ๋ ์ด์์์ด ๊นจ์ง ์ ์์ด์ ์ฃผ์๊ฐ ํ์ํด! โ ๏ธ
import tkinter as tk
root = tk.Tk()
root.title("place() ์์ ")
root.geometry("400x300")
tk.Label(root, text="์ ๋ ์ขํ (50, 50)", bg="#7c9cbf", fg="white").place(x=50, y=50)
tk.Label(root, text="์ ๋ ์ขํ (200, 150)", bg="#66bb6a", fg="white").place(x=200, y=150)
tk.Button(root, text="๋ฒํผ", width=10).place(x=150, y=250)
root.mainloop()
โ ๏ธ ์ฃผ์์ฌํญ
ํ ์ปจํ ์ด๋(ํ๋ ์์ด๋ ์๋์ฐ) ์์์ pack(), grid(), place()๋ฅผ ์์ด์ ์ฌ์ฉํ๋ฉด ์ ๋ผ! ์๋ฌ๊ฐ ๋ฐ์ํ๊ฑฐ๋ ์์์น ๋ชปํ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์ ์์ด. ํ๋์ ๋ ์ด์์ ๊ด๋ฆฌ์๋ง ์ ํํด์ ์ฌ์ฉํ์!
๐ฏ ์ฃผ์ ์์ ฏ๋ค ์์ ์ ๋ณต
์ด์ Tkinter์์ ์์ฃผ ์ฌ์ฉํ๋ ์์ ฏ๋ค์ ํ๋์ฉ ์ดํด๋ณด์! ๊ฐ ์์ ฏ์ ํน์ง๊ณผ ์ฌ์ฉ๋ฒ์ ์๋ฉด ์ ๋ง ๋ค์ํ ํ๋ก๊ทธ๋จ์ ๋ง๋ค ์ ์์ด. ๐ ๏ธ
๐ Text - ์ฌ๋ฌ ์ค ํ ์คํธ ์ ๋ ฅ
Entry๋ ํ ์ค๋ง ์ ๋ ฅ๋ฐ์ ์ ์์ง๋ง, Text ์์ ฏ์ ์ฌ๋ฌ ์ค์ ํ ์คํธ๋ฅผ ์ ๋ ฅ๋ฐ๊ณ ํธ์งํ ์ ์์ด. ๋ฉ๋ชจ์ฅ ๊ฐ์ ํ๋ก๊ทธ๋จ์ ๋ง๋ค ๋ ํ์์ผ!
import tkinter as tk
def save_text():
content = text.get("1.0", tk.END)
print("์ ์ฅ๋ ๋ด์ฉ:")
print(content)
root = tk.Tk()
root.title("Text ์์ ฏ ์์ ")
root.geometry("500x400")
text = tk.Text(root, width=50, height=15, font=("Arial", 11))
text.pack(padx=10, pady=10)
# ์ด๊ธฐ ํ
์คํธ ์ฝ์
text.insert("1.0", "์ฌ๊ธฐ์ ํ
์คํธ๋ฅผ ์
๋ ฅํ์ธ์...\n")
button = tk.Button(root, text="์ ์ฅ", command=save_text)
button.pack(pady=5)
root.mainloop()
get("1.0", tk.END)๋ ์ฒซ ๋ฒ์งธ ์ค์ ์ฒซ ๋ฒ์งธ ๋ฌธ์๋ถํฐ ๋๊น์ง ๋ชจ๋ ํ
์คํธ๋ฅผ ๊ฐ์ ธ์จ๋ค๋ ๋ป์ด์ผ. Tkinter์ Text ์์ ฏ์ "ํ.์ด" ํ์์ผ๋ก ์์น๋ฅผ ์ง์ ํด!
โ๏ธ Checkbutton - ์ฒดํฌ๋ฐ์ค
์ฌ๋ฌ ์ต์ ์ค์์ ์ฌ๋ฌ ๊ฐ๋ฅผ ์ ํํ ์ ์๊ฒ ํด์ฃผ๋ ์์ ฏ์ด์ผ.
import tkinter as tk
def show_selection():
selected = []
if var1.get():
selected.append("Python")
if var2.get():
selected.append("Java")
if var3.get():
selected.append("C++")
result_label.config(text=f"์ ํ๋ ์ธ์ด: {', '.join(selected)}")
root = tk.Tk()
root.title("Checkbutton ์์ ")
root.geometry("400x300")
tk.Label(root, text="์ข์ํ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ ํํ์ธ์:",
font=("Arial", 12)).pack(pady=10)
var1 = tk.BooleanVar()
var2 = tk.BooleanVar()
var3 = tk.BooleanVar()
tk.Checkbutton(root, text="Python ๐", variable=var1,
font=("Arial", 11)).pack(anchor=tk.W, padx=50)
tk.Checkbutton(root, text="Java โ", variable=var2,
font=("Arial", 11)).pack(anchor=tk.W, padx=50)
tk.Checkbutton(root, text="C++ ๐ง", variable=var3,
font=("Arial", 11)).pack(anchor=tk.W, padx=50)
tk.Button(root, text="ํ์ธ", command=show_selection).pack(pady=10)
result_label = tk.Label(root, text="", font=("Arial", 11), fg="#7c9cbf")
result_label.pack(pady=10)
root.mainloop()
BooleanVar()๋ ์ฒดํฌ ์ํ๋ฅผ ์ ์ฅํ๋ ํน๋ณํ ๋ณ์์ผ. True/False ๊ฐ์ ๊ฐ์ง์ง!
๐ Radiobutton - ๋ผ๋์ค ๋ฒํผ
์ฌ๋ฌ ์ต์ ์ค์์ ํ๋๋ง ์ ํํ ์ ์๊ฒ ํด์ฃผ๋ ์์ ฏ์ด์ผ. ์ฒดํฌ๋ฐ์ค์ ๋น์ทํ์ง๋ง ๋ฐฐํ์ ์ ํ์ด ํ์ํ ๋ ์ฌ์ฉํด!
import tkinter as tk
def show_choice():
choice = var.get()
choices = {1: "์ด๊ธ", 2: "์ค๊ธ", 3: "๊ณ ๊ธ"}
result_label.config(text=f"์ ํํ ๋ ๋ฒจ: {choices[choice]}")
root = tk.Tk()
root.title("Radiobutton ์์ ")
root.geometry("400x300")
tk.Label(root, text="๋น์ ์ ํ๋ก๊ทธ๋๋ฐ ๋ ๋ฒจ์?",
font=("Arial", 12, "bold")).pack(pady=10)
var = tk.IntVar()
var.set(1) # ๊ธฐ๋ณธ๊ฐ ์ค์
tk.Radiobutton(root, text="์ด๊ธ ๐ฑ", variable=var, value=1,
font=("Arial", 11)).pack(anchor=tk.W, padx=50)
tk.Radiobutton(root, text="์ค๊ธ ๐ฟ", variable=var, value=2,
font=("Arial", 11)).pack(anchor=tk.W, padx=50)
tk.Radiobutton(root, text="๊ณ ๊ธ ๐ณ", variable=var, value=3,
font=("Arial", 11)).pack(anchor=tk.W, padx=50)
tk.Button(root, text="ํ์ธ", command=show_choice).pack(pady=10)
result_label = tk.Label(root, text="", font=("Arial", 11), fg="#66bb6a")
result_label.pack(pady=10)
root.mainloop()
๊ฐ์ variable์ ๊ณต์ ํ๋ Radiobutton๋ค์ ํ๋์ ๊ทธ๋ฃน์ด ๋์ด์, ํ๋๋ฅผ ์ ํํ๋ฉด ๋ค๋ฅธ ๊ฒ๋ค์ ์๋์ผ๋ก ํด์ ๋ผ!
๐ Listbox - ๋ชฉ๋ก ์์
์ฌ๋ฌ ํญ๋ชฉ์ ๋ฆฌ์คํธ ํํ๋ก ๋ณด์ฌ์ฃผ๊ณ ์ ํํ ์ ์๊ฒ ํด์ฃผ๋ ์์ ฏ์ด์ผ.
import tkinter as tk
def show_selection():
selection = listbox.curselection()
if selection:
index = selection[0]
value = listbox.get(index)
result_label.config(text=f"์ ํ๋ ํญ๋ชฉ: {value}")
root = tk.Tk()
root.title("Listbox ์์ ")
root.geometry("400x350")
tk.Label(root, text="ํ๋ ์์ํฌ๋ฅผ ์ ํํ์ธ์:",
font=("Arial", 12)).pack(pady=10)
listbox = tk.Listbox(root, height=8, font=("Arial", 11))
listbox.pack(padx=20, pady=10)
frameworks = ["Django", "Flask", "FastAPI", "Pyramid", "Tornado",
"Bottle", "CherryPy", "Web2py"]
for framework in frameworks:
listbox.insert(tk.END, framework)
tk.Button(root, text="ํ์ธ", command=show_selection).pack(pady=5)
result_label = tk.Label(root, text="", font=("Arial", 11), fg="#7c9cbf")
result_label.pack(pady=10)
root.mainloop()
๐ Combobox - ์ฝค๋ณด๋ฐ์ค (๋๋กญ๋ค์ด)
Combobox๋ ๊ธฐ๋ณธ Tkinter์๋ ์๊ณ , tkinter.ttk ๋ชจ๋์์ ์ ๊ณตํ๋ ์์ ฏ์ด์ผ. ๋๋กญ๋ค์ด ๋ฉ๋ด๋ฅผ ๋ง๋ค ๋ ์ฌ์ฉํด!
import tkinter as tk
from tkinter import ttk
def show_selection():
selected = combo.get()
result_label.config(text=f"์ ํ๋ ๋์: {selected}")
root = tk.Tk()
root.title("Combobox ์์ ")
root.geometry("400x250")
tk.Label(root, text="๋์๋ฅผ ์ ํํ์ธ์:",
font=("Arial", 12)).pack(pady=10)
combo = ttk.Combobox(root, values=["์์ธ", "๋ถ์ฐ", "๋๊ตฌ", "์ธ์ฒ", "๊ด์ฃผ", "๋์ ", "์ธ์ฐ"],
font=("Arial", 11), state="readonly")
combo.pack(pady=10)
combo.set("์์ธ") # ๊ธฐ๋ณธ๊ฐ ์ค์
tk.Button(root, text="ํ์ธ", command=show_selection).pack(pady=10)
result_label = tk.Label(root, text="", font=("Arial", 11), fg="#66bb6a")
result_label.pack(pady=10)
root.mainloop()
state="readonly"๋ก ์ค์ ํ๋ฉด ์ฌ์ฉ์๊ฐ ์ง์ ์
๋ ฅํ ์ ์๊ณ ๋ชฉ๋ก์์๋ง ์ ํํ ์ ์์ด!
๐๏ธ Scale - ์ฌ๋ผ์ด๋
๋ฒ์ ๋ด์์ ๊ฐ์ ์ ํํ ์ ์๋ ์ฌ๋ผ์ด๋ ์์ ฏ์ด์ผ. ๋ณผ๋ฅจ ์กฐ์ ์ด๋ ๋ฐ๊ธฐ ์กฐ์ ๊ฐ์ ๊ธฐ๋ฅ์ ๋ฑ์ด์ง!
import tkinter as tk
def update_value(val):
result_label.config(text=f"ํ์ฌ ๊ฐ: {int(float(val))}")
root = tk.Tk()
root.title("Scale ์์ ")
root.geometry("400x300")
tk.Label(root, text="๊ฐ์ ์กฐ์ ํ์ธ์:", font=("Arial", 12)).pack(pady=10)
scale = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL,
length=300, command=update_value)
scale.set(50) # ์ด๊ธฐ๊ฐ
scale.pack(pady=20)
result_label = tk.Label(root, text="ํ์ฌ ๊ฐ: 50",
font=("Arial", 14), fg="#7c9cbf")
result_label.pack(pady=10)
root.mainloop()
๐จ Canvas - ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ
Canvas๋ ๋ํ, ์ , ํ ์คํธ, ์ด๋ฏธ์ง ๋ฑ์ ๊ทธ๋ฆด ์ ์๋ ๊ฐ๋ ฅํ ์์ ฏ์ด์ผ. ๊ฒ์์ด๋ ๊ทธ๋ํฝ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ๋ ํ์!
import tkinter as tk
root = tk.Tk()
root.title("Canvas ์์ ")
root.geometry("500x400")
canvas = tk.Canvas(root, width=450, height=350, bg="white")
canvas.pack(padx=10, pady=10)
# ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ
canvas.create_rectangle(50, 50, 150, 150, fill="#7c9cbf", outline="#4a5f7f")
# ์ ๊ทธ๋ฆฌ๊ธฐ
canvas.create_oval(200, 50, 300, 150, fill="#66bb6a", outline="#4caf50")
# ์ ๊ทธ๋ฆฌ๊ธฐ
canvas.create_line(50, 200, 300, 200, fill="#ffa726", width=3)
# ํ
์คํธ ๊ทธ๋ฆฌ๊ธฐ
canvas.create_text(225, 250, text="Tkinter Canvas!",
font=("Arial", 20, "bold"), fill="#4a5f7f")
# ๋ค๊ฐํ ๊ทธ๋ฆฌ๊ธฐ (๋ณ)
points = [225, 280, 240, 315, 275, 315, 245, 335, 255, 370,
225, 350, 195, 370, 205, 335, 175, 315, 210, 315]
canvas.create_polygon(points, fill="#ff6b6b", outline="#c92a2a")
root.mainloop()
๐ญ Frame์ผ๋ก ๋ ์ด์์ ๊ตฌ์ฑํ๊ธฐ
Frame์ ๋ค๋ฅธ ์์ ฏ๋ค์ ๊ทธ๋ฃนํํ๋ ์ปจํ ์ด๋ ์ญํ ์ ํด. ๋ณต์กํ ๋ ์ด์์์ ๋ง๋ค ๋ ์ ๋ง ์ ์ฉํด! ๐๏ธ
import tkinter as tk
root = tk.Tk()
root.title("Frame ์์ ")
root.geometry("500x400")
# ์๋จ ํ๋ ์
top_frame = tk.Frame(root, bg="#7c9cbf", height=100)
top_frame.pack(fill=tk.X, padx=10, pady=5)
tk.Label(top_frame, text="์๋จ ์์ญ", bg="#7c9cbf", fg="white",
font=("Arial", 16, "bold")).pack(pady=30)
# ์ค๊ฐ ํ๋ ์ (์ข์ฐ ๋ถํ )
middle_frame = tk.Frame(root)
middle_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
left_frame = tk.Frame(middle_frame, bg="#e8f5e9", width=200)
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
tk.Label(left_frame, text="์ผ์ชฝ ์์ญ", bg="#e8f5e9",
font=("Arial", 12)).pack(pady=20)
tk.Button(left_frame, text="๋ฒํผ 1").pack(pady=5)
tk.Button(left_frame, text="๋ฒํผ 2").pack(pady=5)
right_frame = tk.Frame(middle_frame, bg="#fff3e0", width=200)
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))
tk.Label(right_frame, text="์ค๋ฅธ์ชฝ ์์ญ", bg="#fff3e0",
font=("Arial", 12)).pack(pady=20)
tk.Entry(right_frame, width=20).pack(pady=5)
tk.Entry(right_frame, width=20).pack(pady=5)
# ํ๋จ ํ๋ ์
bottom_frame = tk.Frame(root, bg="#66bb6a", height=80)
bottom_frame.pack(fill=tk.X, padx=10, pady=5)
tk.Label(bottom_frame, text="ํ๋จ ์์ญ", bg="#66bb6a", fg="white",
font=("Arial", 14)).pack(pady=25)
root.mainloop()
Frame์ ์ฌ์ฉํ๋ฉด ํ๋ฉด์ ๋ ผ๋ฆฌ์ ์ผ๋ก ๋ถํ ํด์ ๊ด๋ฆฌํ ์ ์์ด. ๊ฐ Frame ์์์๋ ๋ ๋ฆฝ์ ์ผ๋ก ๋ ์ด์์ ๊ด๋ฆฌ์๋ฅผ ์ฌ์ฉํ ์ ์์ง!
๐ฌ ๋ฉ์์ง ๋ฐ์ค์ ๋ํ์์
์ฌ์ฉ์์๊ฒ ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ฑฐ๋ ํ์ธ์ ๋ฐ์ ๋ ์ฌ์ฉํ๋ ๋ํ์์๋ค์ด์ผ. tkinter.messagebox ๋ชจ๋์์ ์ ๊ณตํด!
import tkinter as tk
from tkinter import messagebox
def show_info():
messagebox.showinfo("์ ๋ณด", "์ด๊ฒ์ ์ ๋ณด ๋ฉ์์ง์
๋๋ค! โน๏ธ")
def show_warning():
messagebox.showwarning("๊ฒฝ๊ณ ", "์ฃผ์๊ฐ ํ์ํฉ๋๋ค! โ ๏ธ")
def show_error():
messagebox.showerror("์ค๋ฅ", "์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค! โ")
def ask_question():
result = messagebox.askquestion("์ง๋ฌธ", "๊ณ์ํ์๊ฒ ์ต๋๊น?")
if result == 'yes':
label.config(text="Yes๋ฅผ ์ ํํ์ต๋๋ค!")
else:
label.config(text="No๋ฅผ ์ ํํ์ต๋๋ค!")
def ask_okcancel():
result = messagebox.askokcancel("ํ์ธ", "์ ๋ง๋ก ์ญ์ ํ์๊ฒ ์ต๋๊น?")
if result:
label.config(text="์ญ์ ๋์์ต๋๋ค!")
else:
label.config(text="์ทจ์๋์์ต๋๋ค!")
def ask_yesno():
result = messagebox.askyesno("์ ์ฅ", "๋ณ๊ฒฝ์ฌํญ์ ์ ์ฅํ์๊ฒ ์ต๋๊น?")
if result:
label.config(text="์ ์ฅ๋์์ต๋๋ค!")
else:
label.config(text="์ ์ฅํ์ง ์์์ต๋๋ค!")
root = tk.Tk()
root.title("MessageBox ์์ ")
root.geometry("400x450")
tk.Label(root, text="๋ค์ํ ๋ฉ์์ง ๋ฐ์ค",
font=("Arial", 14, "bold")).pack(pady=10)
tk.Button(root, text="์ ๋ณด ๋ฉ์์ง", command=show_info, width=20).pack(pady=5)
tk.Button(root, text="๊ฒฝ๊ณ ๋ฉ์์ง", command=show_warning, width=20).pack(pady=5)
tk.Button(root, text="์ค๋ฅ ๋ฉ์์ง", command=show_error, width=20).pack(pady=5)
tk.Button(root, text="์ง๋ฌธ (Yes/No)", command=ask_question, width=20).pack(pady=5)
tk.Button(root, text="ํ์ธ/์ทจ์", command=ask_okcancel, width=20).pack(pady=5)
tk.Button(root, text="์/์๋์ค", command=ask_yesno, width=20).pack(pady=5)
label = tk.Label(root, text="", font=("Arial", 11), fg="#7c9cbf")
label.pack(pady=20)
root.mainloop()
๐ MessageBox ์ข ๋ฅ
์ ๋ณด ํ์:
โข showinfo() - ์ ๋ณด ๋ฉ์์ง
โข showwarning() - ๊ฒฝ๊ณ ๋ฉ์์ง
โข showerror() - ์ค๋ฅ ๋ฉ์์ง
์ฌ์ฉ์ ์
๋ ฅ ๋ฐ๊ธฐ:
โข askquestion() - Yes/No ์ง๋ฌธ (๋ฐํ๊ฐ: 'yes' ๋๋ 'no')
โข askokcancel() - OK/Cancel (๋ฐํ๊ฐ: True ๋๋ False)
โข askyesno() - Yes/No (๋ฐํ๊ฐ: True ๋๋ False)
โข askretrycancel() - Retry/Cancel (๋ฐํ๊ฐ: True ๋๋ False)
๐ ํ์ผ ๋ํ์์
ํ์ผ์ ์ด๊ฑฐ๋ ์ ์ฅํ ๋ ์ฌ์ฉํ๋ ๋ํ์์์ผ. tkinter.filedialog ๋ชจ๋์์ ์ ๊ณตํด!
import tkinter as tk
from tkinter import filedialog, messagebox
def open_file():
filename = filedialog.askopenfilename(
title="ํ์ผ ์ ํ",
filetypes=(("ํ
์คํธ ํ์ผ", "*.txt"), ("๋ชจ๋ ํ์ผ", "*.*"))
)
if filename:
try:
with open(filename, 'r', encoding='utf-8') as file:
content = file.read()
text.delete("1.0", tk.END)
text.insert("1.0", content)
label.config(text=f"์ด๋ฆฐ ํ์ผ: {filename}")
except Exception as e:
messagebox.showerror("์ค๋ฅ", f"ํ์ผ์ ์ด ์ ์์ต๋๋ค: {str(e)}")
def save_file():
filename = filedialog.asksaveasfilename(
title="ํ์ผ ์ ์ฅ",
defaultextension=".txt",
filetypes=(("ํ
์คํธ ํ์ผ", "*.txt"), ("๋ชจ๋ ํ์ผ", "*.*"))
)
if filename:
try:
content = text.get("1.0", tk.END)
with open(filename, 'w', encoding='utf-8') as file:
file.write(content)
messagebox.showinfo("์ฑ๊ณต", "ํ์ผ์ด ์ ์ฅ๋์์ต๋๋ค!")
label.config(text=f"์ ์ฅ๋ ํ์ผ: {filename}")
except Exception as e:
messagebox.showerror("์ค๋ฅ", f"ํ์ผ์ ์ ์ฅํ ์ ์์ต๋๋ค: {str(e)}")
root = tk.Tk()
root.title("ํ์ผ ๋ํ์์ ์์ ")
root.geometry("600x450")
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
tk.Button(button_frame, text="ํ์ผ ์ด๊ธฐ ๐", command=open_file,
width=15).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="ํ์ผ ์ ์ฅ ๐พ", command=save_file,
width=15).pack(side=tk.LEFT, padx=5)
text = tk.Text(root, width=70, height=20, font=("Arial", 10))
text.pack(padx=10, pady=10)
label = tk.Label(root, text="ํ์ผ์ ์ด๊ฑฐ๋ ์ ์ฅํ์ธ์",
font=("Arial", 10), fg="#6b7c93")
label.pack(pady=5)
root.mainloop()
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋จํ ๋ฉ๋ชจ์ฅ ํ๋ก๊ทธ๋จ์ ๋ง๋ค ์ ์์ด! ๐
๐จ ์คํ์ผ๋ง๊ณผ ํ ๋ง
๊ธฐ๋ณธ Tkinter ์์ ฏ์ ์ข ํฌ๋ฐํด ๋ณด์ผ ์ ์์ด. ํ์ง๋ง tkinter.ttk ๋ชจ๋์ ์ฌ์ฉํ๋ฉด ๋ ํ๋์ ์ธ ์คํ์ผ์ ์ ์ฉํ ์ ์์ด!
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("ttk ์คํ์ผ ์์ ")
root.geometry("500x400")
# ์คํ์ผ ๊ฐ์ฒด ์์ฑ
style = ttk.Style()
# ํ
๋ง ์ ํ (์ฌ์ฉ ๊ฐ๋ฅํ ํ
๋ง: 'clam', 'alt', 'default', 'classic')
style.theme_use('clam')
# ์ปค์คํ
์คํ์ผ ์ ์
style.configure('Custom.TButton',
foreground='white',
background='#7c9cbf',
font=('Arial', 11, 'bold'),
borderwidth=0)
style.map('Custom.TButton',
background=[('active', '#5a7a99')])
tk.Label(root, text="ttk ์์ ฏ ์์ ",
font=("Arial", 16, "bold")).pack(pady=20)
# ttk ๋ฒํผ
ttk.Button(root, text="ttk ๊ธฐ๋ณธ ๋ฒํผ", width=20).pack(pady=5)
ttk.Button(root, text="์ปค์คํ
์คํ์ผ ๋ฒํผ", style='Custom.TButton',
width=20).pack(pady=5)
# ttk Entry
ttk.Entry(root, width=30, font=("Arial", 11)).pack(pady=10)
# ttk Combobox
combo = ttk.Combobox(root, values=["์ต์
1", "์ต์
2", "์ต์
3"],
width=27, state="readonly")
combo.pack(pady=10)
# ttk Progressbar
progress = ttk.Progressbar(root, length=300, mode='determinate')
progress.pack(pady=20)
progress['value'] = 70
root.mainloop()
๐ก ttk vs ๊ธฐ๋ณธ Tkinter
ttk์ ์ฅ์ :
โ
๋ ํ๋์ ์ด๊ณ ์ธ๋ จ๋ ๋์์ธ
โ
์ด์์ฒด์ ๋ค์ดํฐ๋ธ ์คํ์ผ ์ง์
โ
ํ
๋ง ์์คํ
์ผ๋ก ์ผ๊ด๋ ๋์์ธ ์ ์ง
โ
์ถ๊ฐ ์์ ฏ ์ ๊ณต (Treeview, Notebook ๋ฑ)
๊ธฐ๋ณธ Tkinter์ ์ฅ์ :
โ
๋ ๋ง์ ์ปค์คํฐ๋ง์ด์ง ์ต์
โ
๋ ์ธ๋ฐํ ์ ์ด ๊ฐ๋ฅ
โ
์ผ๋ถ ์์ ฏ์ ttk์ ์์ (Canvas, Text ๋ฑ)
๐ฏ ์ด๋ฒคํธ ์ฒ๋ฆฌํ๊ธฐ
์ฌ์ฉ์์ ๋ง์ฐ์ค ํด๋ฆญ, ํค๋ณด๋ ์ ๋ ฅ ๋ฑ์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐ฑ๏ธโจ๏ธ
๐ฑ๏ธ ๋ง์ฐ์ค ์ด๋ฒคํธ
import tkinter as tk
def on_left_click(event):
label.config(text=f"์ผ์ชฝ ํด๋ฆญ! ์์น: ({event.x}, {event.y})")
def on_right_click(event):
label.config(text=f"์ค๋ฅธ์ชฝ ํด๋ฆญ! ์์น: ({event.x}, {event.y})")
def on_double_click(event):
label.config(text="๋๋ธ ํด๋ฆญ!")
def on_mouse_enter(event):
button.config(bg="#5a7a99")
def on_mouse_leave(event):
button.config(bg="#7c9cbf")
root = tk.Tk()
root.title("๋ง์ฐ์ค ์ด๋ฒคํธ ์์ ")
root.geometry("500x400")
tk.Label(root, text="๋ง์ฐ์ค ์ด๋ฒคํธ ํ
์คํธ",
font=("Arial", 14, "bold")).pack(pady=20)
button = tk.Button(root, text="๋ง์ฐ์ค๋ฅผ ์ฌ๋ ค๋ณด์ธ์",
bg="#7c9cbf", fg="white", font=("Arial", 12),
width=20, height=2)
button.pack(pady=20)
# ์ด๋ฒคํธ ๋ฐ์ธ๋ฉ
button.bind("<Button-1>", on_left_click) # ์ผ์ชฝ ํด๋ฆญ
button.bind("<Button-3>", on_right_click) # ์ค๋ฅธ์ชฝ ํด๋ฆญ
button.bind("<Double-Button-1>", on_double_click) # ๋๋ธ ํด๋ฆญ
button.bind("<Enter>", on_mouse_enter) # ๋ง์ฐ์ค ์ง์
button.bind("<Leave>", on_mouse_leave) # ๋ง์ฐ์ค ์ดํ
label = tk.Label(root, text="๋ฒํผ์ ํด๋ฆญํด๋ณด์ธ์!",
font=("Arial", 12), fg="#6b7c93")
label.pack(pady=20)
root.mainloop()
โจ๏ธ ํค๋ณด๋ ์ด๋ฒคํธ
import tkinter as tk
def on_key_press(event):
label.config(text=f"๋๋ฆฐ ํค: {event.keysym} (์ฝ๋: {event.keycode})")
def on_return(event):
text = entry.get()
result_label.config(text=f"์
๋ ฅ๋ ๋ด์ฉ: {text}")
entry.delete(0, tk.END)
def on_escape(event):
root.quit()
root = tk.Tk()
root.title("ํค๋ณด๋ ์ด๋ฒคํธ ์์ ")
root.geometry("500x350")
tk.Label(root, text="ํค๋ณด๋ ์ด๋ฒคํธ ํ
์คํธ",
font=("Arial", 14, "bold")).pack(pady=20)
entry = tk.Entry(root, width=40, font=("Arial", 12))
entry.pack(pady=10)
entry.focus() # ํฌ์ปค์ค ์ค์
tk.Label(root, text="Enter๋ฅผ ๋๋ฅด๋ฉด ์
๋ ฅ ๋ด์ฉ์ด ํ์๋ฉ๋๋ค\nESC๋ฅผ ๋๋ฅด๋ฉด ํ๋ก๊ทธ๋จ์ด ์ข
๋ฃ๋ฉ๋๋ค",
font=("Arial", 10), fg="#6b7c93").pack(pady=10)
# ํค๋ณด๋ ์ด๋ฒคํธ ๋ฐ์ธ๋ฉ
root.bind("<Key>", on_key_press)
entry.bind("<Return>", on_return)
root.bind("<Escape>", on_escape)
label = tk.Label(root, text="ํค๋ฅผ ๋๋ฌ๋ณด์ธ์!",
font=("Arial", 11), fg="#7c9cbf")
label.pack(pady=10)
result_label = tk.Label(root, text="",
font=("Arial", 11, "bold"), fg="#66bb6a")
result_label.pack(pady=10)
root.mainloop()
๐ ์ฃผ์ ์ด๋ฒคํธ ์ข ๋ฅ
๋ง์ฐ์ค ์ด๋ฒคํธ:
โข <Button-1> - ์ผ์ชฝ ๋ฒํผ ํด๋ฆญ
โข <Button-2> - ์ค๊ฐ ๋ฒํผ ํด๋ฆญ
โข <Button-3> - ์ค๋ฅธ์ชฝ ๋ฒํผ ํด๋ฆญ
โข <Double-Button-1> - ๋๋ธ ํด๋ฆญ
โข <Motion> - ๋ง์ฐ์ค ์ด๋
โข <Enter> - ๋ง์ฐ์ค ์ง์
โข <Leave> - ๋ง์ฐ์ค ์ดํ
ํค๋ณด๋ ์ด๋ฒคํธ:
โข <Key> - ์๋ฌด ํค๋ ๋๋ฆผ
โข <Return> - Enter ํค
โข <Escape> - ESC ํค
โข <space> - ์คํ์ด์ค๋ฐ
โข <Control-c> - Ctrl+C
โข <Alt-F4> - Alt+F4
๐ฌ ์ค์ ํ๋ก์ ํธ: ๊ฐ๋จํ ๊ณ์ฐ๊ธฐ ๋ง๋ค๊ธฐ
์ง๊ธ๊น์ง ๋ฐฐ์ด ๋ด์ฉ์ ์ข ํฉํด์ ์ค์ ๋ก ๋์ํ๋ ๊ณ์ฐ๊ธฐ๋ฅผ ๋ง๋ค์ด๋ณด์! ๐งฎ
import tkinter as tk
from tkinter import messagebox
class Calculator:
def __init__(self, root):
self.root = root
self.root.title("๊ณ์ฐ๊ธฐ ๐งฎ")
self.root.geometry("350x450")
self.root.resizable(False, False)
self.expression = ""
self.input_text = tk.StringVar()
self.create_widgets()
def create_widgets(self):
# ์
๋ ฅ ํ๋ฉด
input_frame = tk.Frame(self.root, bg="#f5f7fa")
input_frame.pack(fill=tk.BOTH, padx=10, pady=10)
input_field = tk.Entry(input_frame, textvariable=self.input_text,
font=("Arial", 24), justify=tk.RIGHT,
bd=5, relief=tk.FLAT, bg="#ffffff")
input_field.pack(fill=tk.BOTH, ipady=20)
# ๋ฒํผ ํ๋ ์
button_frame = tk.Frame(self.root, bg="#f5f7fa")
button_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10))
# ๋ฒํผ ์ ์
buttons = [
['C', 'โ', '%', '/'],
['7', '8', '9', '*'],
['4', '5', '6', '-'],
['1', '2', '3', '+'],
['0', '.', '=']
]
# ๋ฒํผ ์์ฑ
for i, row in enumerate(buttons):
for j, button in enumerate(row):
if button == '=':
btn = tk.Button(button_frame, text=button,
font=("Arial", 18, "bold"),
bg="#66bb6a", fg="white",
command=self.calculate)
btn.grid(row=i, column=j, columnspan=2, sticky="nsew", padx=2, pady=2)
elif button == 'C':
btn = tk.Button(button_frame, text=button,
font=("Arial", 18, "bold"),
bg="#ff6b6b", fg="white",
command=self.clear)
btn.grid(row=i, column=j, sticky="nsew", padx=2, pady=2)
elif button == 'โ':
btn = tk.Button(button_frame, text=button,
font=("Arial", 18, "bold"),
bg="#ffa726", fg="white",
command=self.backspace)
btn.grid(row=i, column=j, sticky="nsew", padx=2, pady=2)
elif button in ['/', '*', '-', '+', '%']:
btn = tk.Button(button_frame, text=button,
font=("Arial", 18, "bold"),
bg="#7c9cbf", fg="white",
command=lambda x=button: self.click(x))
btn.grid(row=i, column=j, sticky="nsew", padx=2, pady=2)
else:
btn = tk.Button(button_frame, text=button,
font=("Arial", 18),
bg="#e8ecf1", fg="#2c3e50",
command=lambda x=button: self.click(x))
btn.grid(row=i, column=j, sticky="nsew", padx=2, pady=2)
# ๊ทธ๋ฆฌ๋ ๊ฐ์ค์น ์ค์
for i in range(5):
button_frame.grid_rowconfigure(i, weight=1)
for j in range(4):
button_frame.grid_columnconfigure(j, weight=1)
def click(self, value):
self.expression += str(value)
self.input_text.set(self.expression)
def clear(self):
self.expression = ""
self.input_text.set("")
def backspace(self):
self.expression = self.expression[:-1]
self.input_text.set(self.expression)
def calculate(self):
try:
result = str(eval(self.expression))
self.input_text.set(result)
self.expression = result
except:
messagebox.showerror("์ค๋ฅ", "์๋ชป๋ ์์์
๋๋ค!")
self.expression = ""
self.input_text.set("")
if __name__ == "__main__":
root = tk.Tk()
calculator = Calculator(root)
root.mainloop()
์ด ๊ณ์ฐ๊ธฐ๋ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์์ฑ๋์์ด. ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๋ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ง! ๐
๐ฏ ๊ณ์ฐ๊ธฐ์ ์ฃผ์ ๊ธฐ๋ฅ
โ
๊ธฐ๋ณธ ์ฌ์น์ฐ์ฐ (+, -, *, /)
โ
๋๋จธ์ง ์ฐ์ฐ (%)
โ
์์์ ์
๋ ฅ
โ
์ง์ฐ๊ธฐ (C) ๊ธฐ๋ฅ
โ
๋ฐฑ์คํ์ด์ค (โ) ๊ธฐ๋ฅ
โ
์ค๋ฅ ์ฒ๋ฆฌ
๐จ ๋ฉ๋ด๋ฐ ๋ง๋ค๊ธฐ
์ ๋ฌธ์ ์ธ ํ๋ก๊ทธ๋จ์๋ ๋ฉ๋ด๋ฐ๊ฐ ํ์์ง! ํ์ผ, ํธ์ง, ๋์๋ง ๊ฐ์ ๋ฉ๋ด๋ฅผ ๋ง๋ค์ด๋ณด์.
import tkinter as tk
from tkinter import messagebox, filedialog
def new_file():
text.delete("1.0", tk.END)
root.title("์ ๋ชฉ ์์ - ๋ฉ๋ชจ์ฅ")
def open_file():
filename = filedialog.askopenfilename(
defaultextension=".txt",
filetypes=[("ํ
์คํธ ํ์ผ", "*.txt"), ("๋ชจ๋ ํ์ผ", "*.*")]
)
if filename:
with open(filename, 'r', encoding='utf-8') as file:
text.delete("1.0", tk.END)
text.insert("1.0", file.read())
root.title(f"{filename} - ๋ฉ๋ชจ์ฅ")
def save_file():
filename = filedialog.asksaveasfilename(
defaultextension=".txt",
filetypes=[("ํ
์คํธ ํ์ผ", "*.txt"), ("๋ชจ๋ ํ์ผ", "*.*")]
)
if filename:
with open(filename, 'w', encoding='utf-8') as file:
file.write(text.get("1.0", tk.END))
root.title(f"{filename} - ๋ฉ๋ชจ์ฅ")
messagebox.showinfo("์ ์ฅ", "ํ์ผ์ด ์ ์ฅ๋์์ต๋๋ค!")
def exit_app():
if messagebox.askokcancel("์ข
๋ฃ", "์ ๋ง๋ก ์ข
๋ฃํ์๊ฒ ์ต๋๊น?"):
root.quit()
def about():
messagebox.showinfo("์ ๋ณด", "๊ฐ๋จํ ๋ฉ๋ชจ์ฅ ํ๋ก๊ทธ๋จ\n๋ฒ์ 1.0\n\nTkinter๋ก ๋ง๋ค์์ต๋๋ค! ๐")
root = tk.Tk()
root.title("์ ๋ชฉ ์์ - ๋ฉ๋ชจ์ฅ")
root.geometry("700x500")
# ๋ฉ๋ด๋ฐ ์์ฑ
menubar = tk.Menu(root)
root.config(menu=menubar)
# ํ์ผ ๋ฉ๋ด
file_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="ํ์ผ", menu=file_menu)
file_menu.add_command(label="์ ํ์ผ", command=new_file, accelerator="Ctrl+N")
file_menu.add_command(label="์ด๊ธฐ", command=open_file, accelerator="Ctrl+O")
file_menu.add_command(label="์ ์ฅ", command=save_file, accelerator="Ctrl+S")
file_menu.add_separator()
file_menu.add_command(label="์ข
๋ฃ", command=exit_app, accelerator="Ctrl+Q")
# ํธ์ง ๋ฉ๋ด
edit_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="ํธ์ง", menu=edit_menu)
edit_menu.add_command(label="์คํ ์ทจ์", command=lambda: text.edit_undo())
edit_menu.add_command(label="๋ค์ ์คํ", command=lambda: text.edit_redo())
edit_menu.add_separator()
edit_menu.add_command(label="์๋ผ๋ด๊ธฐ", command=lambda: text.event_generate("<<Cut>>"))
edit_menu.add_command(label="๋ณต์ฌ", command=lambda: text.event_generate("<<Copy>>"))
edit_menu.add_command(label="๋ถ์ฌ๋ฃ๊ธฐ", command=lambda: text.event_generate("<<Paste>>"))
# ๋์๋ง ๋ฉ๋ด
help_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="๋์๋ง", menu=help_menu)
help_menu.add_command(label="์ ๋ณด", command=about)
# ํ
์คํธ ์์ ฏ
text = tk.Text(root, font=("๋ง์ ๊ณ ๋", 11), undo=True, wrap=tk.WORD)
text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# ์คํฌ๋กค๋ฐ
scrollbar = tk.Scrollbar(text)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
text.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=text.yview)
# ํค๋ณด๋ ๋จ์ถํค ๋ฐ์ธ๋ฉ
root.bind('<Control-n>', lambda e: new_file())
root.bind('<Control-o>', lambda e: open_file())
root.bind('<Control-s>', lambda e: save_file())
root.bind('<Control-q>', lambda e: exit_app())
root.mainloop()
tearoff=0์ ๋ฉ๋ด๋ฅผ ๋ถ๋ฆฌํ ์ ์๊ฒ ๋ง๋๋ ์ต์
์ด์ผ. ๊ธฐ๋ณธ๊ฐ์ 1์ธ๋ฐ, ๊ทธ๋ฌ๋ฉด ๋ฉ๋ด๋ฅผ ๋ผ์ด๋ผ ์ ์๋ ์ ์ ์ด ์๊ฒจ!
๐ผ๏ธ ์ด๋ฏธ์ง ๋ค๋ฃจ๊ธฐ
Tkinter์์ ์ด๋ฏธ์ง๋ฅผ ํ์ํ๋ ค๋ฉด PIL (Pillow) ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ข์. ๋ค์ํ ์ด๋ฏธ์ง ํฌ๋งท์ ์ง์ํ๊ฑฐ๋ !
# Pillow ์ค์น: pip install Pillow
import tkinter as tk
from PIL import Image, ImageTk
from tkinter import filedialog, messagebox
def load_image():
filename = filedialog.askopenfilename(
title="์ด๋ฏธ์ง ์ ํ",
filetypes=[("์ด๋ฏธ์ง ํ์ผ", "*.png *.jpg *.jpeg *.gif *.bmp"),
("๋ชจ๋ ํ์ผ", "*.*")]
)
if filename:
try:
# ์ด๋ฏธ์ง ์ด๊ธฐ
image = Image.open(filename)
# ์ด๋ฏธ์ง ํฌ๊ธฐ ์กฐ์ (์ต๋ 500x500)
image.thumbnail((500, 500), Image.Resampling.LANCZOS)
# PhotoImage๋ก ๋ณํ
photo = ImageTk.PhotoImage(image)
# Label์ ์ด๋ฏธ์ง ํ์
image_label.config(image=photo)
image_label.image = photo # ์ฐธ์กฐ ์ ์ง (์ค์!)
info_label.config(text=f"ํ์ผ: {filename}\nํฌ๊ธฐ: {image.size}")
except Exception as e:
messagebox.showerror("์ค๋ฅ", f"์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค: {str(e)}")
root = tk.Tk()
root.title("์ด๋ฏธ์ง ๋ทฐ์ด ๐ผ๏ธ")
root.geometry("600x650")
tk.Label(root, text="์ด๋ฏธ์ง ๋ทฐ์ด",
font=("Arial", 16, "bold")).pack(pady=10)
tk.Button(root, text="์ด๋ฏธ์ง ๋ถ๋ฌ์ค๊ธฐ ๐", command=load_image,
font=("Arial", 12), bg="#7c9cbf", fg="white",
width=20).pack(pady=10)
# ์ด๋ฏธ์ง ํ์ ์์ญ
image_frame = tk.Frame(root, bg="#f5f7fa", width=520, height=520)
image_frame.pack(padx=10, pady=10)
image_frame.pack_propagate(False)
image_label = tk.Label(image_frame, text="์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ค์ธ์",
font=("Arial", 12), bg="#f5f7fa", fg="#6b7c93")
image_label.pack(expand=True)
info_label = tk.Label(root, text="", font=("Arial", 10), fg="#6b7c93")
info_label.pack(pady=5)
root.mainloop()
โ ๏ธ ์ค์ํ ์ฃผ์์ฌํญ
image_label.image = photo ์ด ์ค์ด ์ ๋ง ์ค์ํด! ์ด๋ ๊ฒ ์ฐธ์กฐ๋ฅผ ์ ์งํ์ง ์์ผ๋ฉด ์ด๋ฏธ์ง๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์
๋์ด์ ํ๋ฉด์ ํ์๋์ง ์์. ์ด๊ฑด Tkinter์ ํน์ฑ์ด๋๊น ๊ผญ ๊ธฐ์ตํด๋ฌ!
โฐ ํ์ด๋จธ์ ์ ๋๋ฉ์ด์
after() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ผ์ ์๊ฐ ํ์ ํจ์๋ฅผ ์คํํ ์ ์์ด. ์ด๊ฑธ ํ์ฉํ๋ฉด ํ์ด๋จธ๋ ์ ๋๋ฉ์ด์
์ ๋ง๋ค ์ ์์ง!
import tkinter as tk
from datetime import datetime
class DigitalClock:
def __init__(self, root):
self.root = root
self.root.title("๋์งํธ ์๊ณ โฐ")
self.root.geometry("400x200")
self.root.configure(bg="#2c3e50")
self.time_label = tk.Label(root, font=("Arial", 48, "bold"),
bg="#2c3e50", fg="#ecf0f1")
self.time_label.pack(expand=True)
self.date_label = tk.Label(root, font=("Arial", 16),
bg="#2c3e50", fg="#bdc3c7")
self.date_label.pack()
self.update_time()
def update_time(self):
now = datetime.now()
time_string = now.strftime("%H:%M:%S")
date_string = now.strftime("%Y๋
%m์ %d์ผ %A")
self.time_label.config(text=time_string)
self.date_label.config(text=date_string)
# 1000ms(1์ด) ํ์ ๋ค์ ํธ์ถ
self.root.after(1000, self.update_time)
if __name__ == "__main__":
root = tk.Tk()
clock = DigitalClock(root)
root.mainloop()
๐จ Canvas ์ ๋๋ฉ์ด์
import tkinter as tk
import random
class BouncingBall:
def __init__(self, root):
self.root = root
self.root.title("ํ๋ ๊ณต ์ ๋๋ฉ์ด์
โฝ")
self.root.geometry("600x500")
self.canvas = tk.Canvas(root, width=600, height=450, bg="#ecf0f1")
self.canvas.pack(pady=10)
# ๊ณต ์์ฑ
self.ball = self.canvas.create_oval(275, 225, 325, 275,
fill="#e74c3c", outline="")
# ์๋
self.dx = random.choice([-5, -4, -3, 3, 4, 5])
self.dy = random.choice([-5, -4, -3, 3, 4, 5])
# ๋ฒํผ
tk.Button(root, text="์์/์ ์ง", command=self.toggle,
font=("Arial", 12), bg="#3498db", fg="white",
width=15).pack(pady=5)
self.running = False
self.animate()
def toggle(self):
self.running = not self.running
def animate(self):
if self.running:
# ํ์ฌ ์์น ๊ฐ์ ธ์ค๊ธฐ
pos = self.canvas.coords(self.ball)
# ๋ฒฝ์ ๋ถ๋ชํ๋ฉด ๋ฐฉํฅ ๋ฐ์
if pos[0] <= 0 or pos[2] >= 600:
self.dx = -self.dx
if pos[1] <= 0 or pos[3] >= 450:
self.dy = -self.dy
# ๊ณต ์ด๋
self.canvas.move(self.ball, self.dx, self.dy)
# 30ms ํ์ ๋ค์ ํธ์ถ (์ฝ 33 FPS)
self.root.after(30, self.animate)
if __name__ == "__main__":
root = tk.Tk()
app = BouncingBall(root)
root.mainloop()
์ด๋ ๊ฒ after()๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํ๋ฉด ๋ถ๋๋ฌ์ด ์ ๋๋ฉ์ด์
์ ๋ง๋ค ์ ์์ด! ๐ฌ
๐พ ๋ฐ์ดํฐ ์ ์ฅํ๊ธฐ (JSON ํ์ฉ)
ํ๋ก๊ทธ๋จ์ ์ข ๋ฃํด๋ ๋ฐ์ดํฐ๋ฅผ ์ ์งํ๋ ค๋ฉด ํ์ผ์ ์ ์ฅํด์ผ ํด. JSON ํ์์ ์ฌ์ฉํ๋ฉด ํธ๋ฆฌํด!
import tkinter as tk
from tkinter import messagebox
import json
import os
class TodoApp:
def __init__(self, root):
self.root = root
self.root.title("ํ ์ผ ๋ชฉ๋ก ๐")
self.root.geometry("500x600")
self.filename = "todos.json"
self.todos = self.load_todos()
self.create_widgets()
self.refresh_list()
def create_widgets(self):
# ์ ๋ชฉ
tk.Label(self.root, text="ํ ์ผ ๋ชฉ๋ก",
font=("Arial", 18, "bold")).pack(pady=10)
# ์
๋ ฅ ํ๋ ์
input_frame = tk.Frame(self.root)
input_frame.pack(pady=10, padx=20, fill=tk.X)
self.entry = tk.Entry(input_frame, font=("Arial", 12))
self.entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 10))
self.entry.bind("<Return>", lambda e: self.add_todo())
tk.Button(input_frame, text="์ถ๊ฐ", command=self.add_todo,
bg="#66bb6a", fg="white", font=("Arial", 11),
width=8).pack(side=tk.LEFT)
# ๋ฆฌ์คํธ๋ฐ์ค
list_frame = tk.Frame(self.root)
list_frame.pack(pady=10, padx=20, fill=tk.BOTH, expand=True)
scrollbar = tk.Scrollbar(list_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.listbox = tk.Listbox(list_frame, font=("Arial", 11),
yscrollcommand=scrollbar.set,
selectmode=tk.SINGLE)
self.listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.config(command=self.listbox.yview)
# ๋ฒํผ ํ๋ ์
button_frame = tk.Frame(self.root)
button_frame.pack(pady=10)
tk.Button(button_frame, text="์๋ฃ", command=self.complete_todo,
bg="#7c9cbf", fg="white", font=("Arial", 11),
width=10).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="์ญ์ ", command=self.delete_todo,
bg="#ff6b6b", fg="white", font=("Arial", 11),
width=10).pack(side=tk.LEFT, padx=5)
def load_todos(self):
if os.path.exists(self.filename):
try:
with open(self.filename, 'r', encoding='utf-8') as f:
return json.load(f)
except:
return []
return []
def save_todos(self):
with open(self.filename, 'w', encoding='utf-8') as f:
json.dump(self.todos, f, ensure_ascii=False, indent=2)
def add_todo(self):
text = self.entry.get().strip()
if text:
self.todos.append({"text": text, "completed": False})
self.save_todos()
self.refresh_list()
self.entry.delete(0, tk.END)
else:
messagebox.showwarning("๊ฒฝ๊ณ ", "ํ ์ผ์ ์
๋ ฅํ์ธ์!")
def complete_todo(self):
selection = self.listbox.curselection()
if selection:
index = selection[0]
self.todos[index]["completed"] = not self.todos[index]["completed"]
self.save_todos()
self.refresh_list()
def delete_todo(self):
selection = self.listbox.curselection()
if selection:
if messagebox.askyesno("ํ์ธ", "์ ๋ง๋ก ์ญ์ ํ์๊ฒ ์ต๋๊น?"):
index = selection[0]
del self.todos[index]
self.save_todos()
self.refresh_list()
def refresh_list(self):
self.listbox.delete(0, tk.END)
for todo in self.todos:
text = todo["text"]
if todo["completed"]:
text = "โ " + text
else:
text = "โ " + text
self.listbox.insert(tk.END, text)
if __name__ == "__main__":
root = tk.Tk()
app = TodoApp(root)
root.mainloop()
์ด ํ ์ผ ๋ชฉ๋ก ์ฑ์ JSON ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ ํ๋ก๊ทธ๋จ์ ๋ค์ ์คํํด๋ ๋ฐ์ดํฐ๊ฐ ์ ์ง๋ผ! ๐พ
๐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค
๐ช Toplevel - ์ ์ฐฝ ๋ง๋ค๊ธฐ
๋ฉ์ธ ์ฐฝ ์ธ์ ์ถ๊ฐ๋ก ์ฐฝ์ ๋์ฐ๊ณ ์ถ์ ๋ ์ฌ์ฉํด!
import tkinter as tk
def open_settings():
settings_window = tk.Toplevel(root)
settings_window.title("์ค์ ")
settings_window.geometry("400x300")
tk.Label(settings_window, text="์ค์ ",
font=("Arial", 16, "bold")).pack(pady=20)
tk.Label(settings_window, text="ํ
๋ง:").pack(pady=5)
theme_var = tk.StringVar(value="๋ฐ์")
tk.Radiobutton(settings_window, text="๋ฐ์",
variable=theme_var, value="๋ฐ์").pack()
tk.Radiobutton(settings_window, text="์ด๋์",
variable=theme_var, value="์ด๋์").pack()
tk.Button(settings_window, text="๋ซ๊ธฐ",
command=settings_window.destroy).pack(pady=20)
root = tk.Tk()
root.title("๋ฉ์ธ ์ฐฝ")
root.geometry("400x300")
tk.Label(root, text="๋ฉ์ธ ์ฐฝ",
font=("Arial", 16, "bold")).pack(pady=50)
tk.Button(root, text="์ค์ ์ด๊ธฐ", command=open_settings,
font=("Arial", 12)).pack()
root.mainloop()
๐ Notebook - ํญ ์ธํฐํ์ด์ค
์ฌ๋ฌ ํ์ด์ง๋ฅผ ํญ์ผ๋ก ๊ตฌ๋ถํ ์ ์์ด!
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("Notebook ์์ ")
root.geometry("600x400")
# Notebook ์์ฑ
notebook = ttk.Notebook(root)
notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# ํญ 1
tab1 = tk.Frame(notebook, bg="#e8f5e9")
notebook.add(tab1, text="ํ ๐ ")
tk.Label(tab1, text="ํ ํญ์
๋๋ค", font=("Arial", 16, "bold"),
bg="#e8f5e9").pack(pady=50)
tk.Button(tab1, text="๋ฒํผ 1").pack()
# ํญ 2
tab2 = tk.Frame(notebook, bg="#fff3e0")
notebook.add(tab2, text="ํ๋กํ ๐ค")
tk.Label(tab2, text="ํ๋กํ ํญ์
๋๋ค", font=("Arial", 16, "bold"),
bg="#fff3e0").pack(pady=50)
tk.Entry(tab2, width=30).pack(pady=5)
# ํญ 3
tab3 = tk.Frame(notebook, bg="#e3f2fd")
notebook.add(tab3, text="์ค์ โ๏ธ")
tk.Label(tab3, text="์ค์ ํญ์
๋๋ค", font=("Arial", 16, "bold"),
bg="#e3f2fd").pack(pady=50)
tk.Checkbutton(tab3, text="์๋ฆผ ๋ฐ๊ธฐ", bg="#e3f2fd").pack()
root.mainloop()
๐ณ Treeview - ํธ๋ฆฌ ๊ตฌ์กฐ ํ์
๊ณ์ธต์ ๋ฐ์ดํฐ๋ ํ ํํ์ ๋ฐ์ดํฐ๋ฅผ ํ์ํ ๋ ์ ์ฉํด!
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("Treeview ์์ ")
root.geometry("700x400")
# Treeview ์์ฑ
tree = ttk.Treeview(root, columns=("์ด๋ฆ", "๋์ด", "์ง์
"), show="tree headings")
tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# ์ด ์ค์
tree.heading("#0", text="ID")
tree.heading("์ด๋ฆ", text="์ด๋ฆ")
tree.heading("๋์ด", text="๋์ด")
tree.heading("์ง์
", text="์ง์
")
tree.column("#0", width=100)
tree.column("์ด๋ฆ", width=150)
tree.column("๋์ด", width=100)
tree.column("์ง์
", width=200)
# ๋ฐ์ดํฐ ์ถ๊ฐ
tree.insert("", "end", text="001", values=("๊น์ฒ ์", "30", "๊ฐ๋ฐ์"))
tree.insert("", "end", text="002", values=("์ด์ํฌ", "28", "๋์์ด๋"))
tree.insert("", "end", text="003", values=("๋ฐ๋ฏผ์", "35", "๊ธฐํ์"))
# ๊ณ์ธต ๊ตฌ์กฐ ์์
parent = tree.insert("", "end", text="ํ", values=("๊ฐ๋ฐํ", "", ""))
tree.insert(parent, "end", text="004", values=("์ต์งํ", "27", "์ฃผ๋์ด ๊ฐ๋ฐ์"))
tree.insert(parent, "end", text="005", values=("์ ์์ง", "32", "์๋์ด ๊ฐ๋ฐ์"))
root.mainloop()
๐ฏ ์ค๋ฌด ํ๊ณผ ๋ฒ ์คํธ ํ๋ํฐ์ค
โจ ์ฝ๋ ์์ฑ ํ
1. ํด๋์ค ๊ธฐ๋ฐ ๊ตฌ์กฐ ์ฌ์ฉํ๊ธฐ
๋ณต์กํ ํ๋ก๊ทธ๋จ์ ํด๋์ค๋ก ๊ตฌ์กฐํํ๋ฉด ๊ด๋ฆฌ๊ฐ ํจ์ฌ ์ฌ์์ ธ. ์์ ฏ๋ค์ ์ธ์คํด์ค ๋ณ์๋ก ์ ์ฅํ๊ณ , ๋ฉ์๋๋ก ๊ธฐ๋ฅ์ ๋ถ๋ฆฌํ์!
2. ๋ ์ด์์ ๊ด๋ฆฌ์ ์ผ๊ด์ฑ ์ ์ง
ํ ์ปจํ
์ด๋ ์์์๋ ํ๋์ ๋ ์ด์์ ๊ด๋ฆฌ์๋ง ์ฌ์ฉํด. pack(), grid(), place()๋ฅผ ์์ด ์ฐ๋ฉด ์ ๋ผ!
3. ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ถ๋ฆฌ
lambda ๋์ ๋ณ๋์ ํจ์๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ง๋ค๋ฉด ๋๋ฒ๊น
์ด ์ฌ์์ ธ.
4. ์์ธ ์ฒ๋ฆฌ ํ์
ํ์ผ ์
์ถ๋ ฅ, ๋คํธ์ํฌ ํต์ ๋ฑ์๋ ํญ์ try-except๋ฅผ ์ฌ์ฉํด์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ์!
5. ๋ฆฌ์์ค ์ ๋ฆฌ
ํ๋ก๊ทธ๋จ ์ข
๋ฃ ์ ์ด๋ฆฐ ํ์ผ์ด๋ ์ฐ๊ฒฐ์ ์ ๋๋ก ๋ซ์์ฃผ์.
๐ก ์ฑ๋ฅ ์ต์ ํ ํ
โข ๋ฌด๊ฑฐ์ด ์์
์ ์ค๋ ๋๋ก ๋ถ๋ฆฌํด์ GUI๊ฐ ๋ฉ์ถ์ง ์๊ฒ ํ๊ธฐ
โข ์ด๋ฏธ์ง๋ ํ์ํ ํฌ๊ธฐ๋ก ๋ฏธ๋ฆฌ ์กฐ์ ํ๊ธฐ
โข Canvas์ ๋๋ฌด ๋ง์ ๊ฐ์ฒด๋ฅผ ๊ทธ๋ฆฌ์ง ์๊ธฐ
โข after()์ ๊ฐ๊ฒฉ์ ๋๋ฌด ์งง๊ฒ ์ค์ ํ์ง ์๊ธฐ
๐ ๋ ๋์๊ฐ๊ธฐ
Tkinter์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ๋ค๋ฉด, ์ด์ ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ํํํด๋ณผ ์ฐจ๋ก์ผ! ๐บ๏ธ
๐จ ๋ค์ ๋จ๊ณ ํ์ต ์ฃผ์
1. ์ค๋ ๋ฉ (Threading)
๊ธด ์์
์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํํด์ GUI๊ฐ ๋ฉ์ถ์ง ์๊ฒ ๋ง๋ค๊ธฐ
2. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋
SQLite๋ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํด์ ๋ฐ์ดํฐ ๊ด๋ฆฌํ๊ธฐ
3. ๋คํธ์ํน
์์ผ ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ์ฑํ
ํ๋ก๊ทธ๋จ์ด๋ ํด๋ผ์ด์ธํธ-์๋ฒ ์ ํ๋ฆฌ์ผ์ด์
๋ง๋ค๊ธฐ
4. ์ปค์คํ
์์ ฏ
๊ธฐ์กด ์์ ฏ์ ์์๋ฐ์ ๋๋ง์ ์์ ฏ ๋ง๋ค๊ธฐ
5. ํจํค์ง
PyInstaller๋ก ์คํ ํ์ผ(.exe) ๋ง๋ค์ด์ ๋ฐฐํฌํ๊ธฐ
๐ ์ฌ๋ฅ๋ท์์ ๋ ๋ฐฐ์ฐ๊ธฐ
Tkinter๋ฅผ ๋ฐฐ์ฐ๋ฉด์ ๋งํ๋ ๋ถ๋ถ์ด ์๊ฑฐ๋, ๋ ์ ๋ฌธ์ ์ธ ํ๋ก์ ํธ๋ฅผ ์งํํ๊ณ ์ถ๋ค๋ฉด ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ ํ์ฉํด๋ณด๋ ๊ฒ๋ ์ข์! ๐จโ๐ซ
์ฌ๋ฅ๋ท์๋ ํ์ด์ฌ GUI ํ๋ก๊ทธ๋๋ฐ ์ ๋ฌธ๊ฐ๋ค์ด ๋ง์ด ์์ด์, 1:1 ๊ณผ์ธ๋ ํ๋ก์ ํธ ๋ฉํ ๋ง์ ๋ฐ์ ์ ์์ด. ์ค๋ฌด์์ ์ฌ์ฉํ๋ ๊ณ ๊ธ ๊ธฐ๋ฒ์ด๋ ๋์์ธ ํจํด์ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด ์ ๋ฌธ๊ฐ์ ๋์์ ๋ฐ๋ ๊ฒ ํจ์ฌ ๋น ๋ฅด์ง!
๋ํ ์์ ์ด Tkinter์ ๋ฅ์ํด์ก๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๊ฐ๋ฅด์ณ์ฃผ๋ฉด์ ์์ต๋ ์ฐฝ์ถํ ์ ์์ด. ์ง์์ ๋๋๋ ๊ฒ๋ ์ ๋ง ๋ณด๋์ฐฌ ์ผ์ด๊ฑฐ๋ ! ๐
๐ฌ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์, ์ฌ๊ธฐ๊น์ง Tkinter์ ๊ธฐ๋ณธ๋ถํฐ ์ค์ ํ๋ก์ ํธ๊น์ง ํจ๊ป ์ดํด๋ดค์ด! ๐
์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ํ๋์ฉ ๋ฐ๋ผ ํ๋ค ๋ณด๋ฉด ์ด๋์ ๋ฉ์ง GUI ํ๋ก๊ทธ๋จ์ ๋ง๋ค ์ ์๊ฒ ๋ ๊ฑฐ์ผ. ์ค์ํ ๊ฑด **์ง์ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๋ ๊ฒ**์ด์ผ! ๐
๐ฏ ํต์ฌ ์์ฝ
โ
Tkinter๋ ํ์ด์ฌ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ GUI ํดํท
โ
์์ ฏ(Widget)์ผ๋ก ๋ค์ํ UI ์์ ๊ตฌ์ฑ
โ
pack(), grid(), place()๋ก ๋ ์ด์์ ๊ด๋ฆฌ
โ
์ด๋ฒคํธ ๋ฐ์ธ๋ฉ์ผ๋ก ์ฌ์ฉ์ ์ํธ์์ฉ ์ฒ๋ฆฌ
โ
ํด๋์ค ๊ธฐ๋ฐ ๊ตฌ์กฐ๋ก ์ฒด๊ณ์ ์ธ ์ฝ๋ ์์ฑ
โ
ttk ๋ชจ๋๋ก ๋ ํ๋์ ์ธ ๋์์ธ ๊ตฌํ
โ
์ค์ ํ๋ก์ ํธ๋ก ์ค๋ ฅ ํฅ์
์ด์ ๋น์ ๋ Tkinter ๋ง์คํฐ๊ฐ ๋ ์ค๋น๊ฐ ๋์์ด! ๐ช ์์ ํ๋ก์ ํธ๋ถํฐ ์์ํด์ ์ ์ ๋ณต์กํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋์๊ฐ๋ณด์. ์คํจ๋ฅผ ๋๋ ค์ํ์ง ๋ง๊ณ , ์๋ฌ ๋ฉ์์ง๋ฅผ ์น๊ตฌ์ฒ๋ผ ๋ํ๋ฉด์ ๋ฐฐ์๋๊ฐ๋ฉด ๋ผ!
๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ๋งํ๋ ๋ถ๋ถ์ด ์๋ค๋ฉด ๊ณต์ ๋ฌธ์(https://docs.python.org/3/library/tkinter.html)๋ฅผ ์ฐธ๊ณ ํ๊ฑฐ๋, ์ปค๋ฎค๋ํฐ์ ์ง๋ฌธํด๋ณด์. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฅ๋ท์์ ์ ๋ฌธ๊ฐ์ ๋์์ ๋ฐ๋ ๊ฒ๋ ์์ง ๋ง๊ณ ! ๐
์, ์ด์ ๋น์ ์ ์ฐฝ์๋ ฅ์ ๋ฐํํด์ ๋ฉ์ง ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์! ํ์ดํ ! ๐๐
Happy Tkinter Programming! ๐โจ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.