Tkinter

JOOYEUN SEOยท2024๋…„ 9์›” 11์ผ

100 Days of Python

๋ชฉ๋ก ๋ณด๊ธฐ
29/76
post-thumbnail

๐Ÿ—‚๏ธ Day29 ํ”„๋กœ์ ํŠธ: ํŒจ์Šค์›Œ๋“œ ๋งค๋‹ˆ์ € GUI

Tkinter ๋ชจ๋“ˆ๋กœ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ…์ŠคํŠธ ํŒŒ์ผ์— ์ €์žฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ

1. ์ด๋ฏธ์ง€๋ฅผ ๋‹ค๋ฃจ๊ณ  ์บ”๋ฒ„์Šค ์„ค์ •ํ•˜๊ธฐ

๐Ÿ” ์œ ์˜ ์‚ฌํ•ญ

โŒจ๏ธ main.py

from tkinter import *

# ---------------------------- UI SETUP ------------------------------- #
window = Tk()
window.title("Passwork Manager")
window.config(padx=20, pady=20)

canvas = Canvas(width=200, height=200)
logo_img = PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=logo_img)
canvas.grid()

window.mainloop()

2. grid()์™€ columnspan์œผ๋กœ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์™„์„ฑํ•˜๊ธฐ

๐Ÿ” ์œ ์˜ ์‚ฌํ•ญ

  • ๋ ˆ์ด์•„์›ƒ : 5ํ–‰ 3์—ด
  • ์œ„์ ฏ ํ•˜๋‚˜๊ฐ€ ์—ฌ๋Ÿฌ ์—ด์„ ๊ฑธ์น˜๋„๋ก ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค
    widget.grid( โ€ฆ, columnspan=num ) : grid์˜ ์†์„ฑ์œผ๋กœ, ํ•ด๋‹น ์œ„์ ฏ์ด numnum๊ฐœ์˜ ์—ด์— ๊ฑธ์ณ์ง
from tkinter import *
window = Tk()
# ๋นจ๊ฐ•์ƒ‰ ์ƒ์ž
r = Label(bg="red", width=20, height=5)
r.grid(row=0, column=0)
# ์ดˆ๋ก์ƒ‰ ์ƒ์ž
g = Label(bg="green", width=20, height=5)
g.grid(row=1, column=1)
# ํŒŒ๋ž€์ƒ‰ ์ƒ์ž
b = Label(bg="blue", width=40, height=5)
b.grid(row=2, column=0, columnspan=2)

โŒจ๏ธ main.py

from tkinter import *

# ---------------------------- UI SETUP ------------------------------- #
window = Tk()
window.title("Passwork Manager")
window.config(padx=50, pady=50)

# ์บ”๋ฒ„์Šค
canvas = Canvas(width=200, height=200)
logo_img = PhotoImage(file="logo.png")
canvas.create_image(130, 100, image=logo_img)
canvas.grid(row=0, column=1)

# ๋ ˆ์ด๋ธ”
website_label = Label(text="Website:")
website_label.grid(row=1, column=0)
email_label = Label(text="Email/Username:")
email_label.grid(row=2, column=0)
password_label = Label(text="Password:")
password_label.grid(row=3, column=0)

# ์—”ํŠธ๋ฆฌ
website_entry = Entry(width=38)
website_entry.grid(row=1, column=1, columnspan=2)
email_entry = Entry(width=38)
email_entry.grid(row=2, column=1, columnspan=2)
password_entry = Entry(width=21)
password_entry.grid(row=3, column=1)

# ๋ฒ„ํŠผ
generate_password_button = Button(text="Generate Password")
generate_password_button.grid(row=3, column=2)
add_button = Button(text="Add", width=36)
add_button.grid(row=4, column=1, columnspan=2)

window.mainloop()

3. ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์ผ์— ์ €์žฅํ•˜๊ธฐ

๐Ÿ” ์œ ์˜ ์‚ฌํ•ญ

  • ์‹œ์ž‘ํ•˜์ž๋งˆ์ž ์ปค์„œ๊ฐ€ website๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ํ™œ์„ฑํ™”๋˜๋„๋ก ๋ฐ”๊พธ๊ธฐ
    entry.focus() : ์ปค์„œ๋ฅผ ํ•ด๋‹น ์—”ํŠธ๋ฆฌ ์ž…๋ ฅ ํ•„๋“œ๋กœ ํฌ์ปค์‹ฑ
  • email ํ•„๋“œ๋Š” ๋ฏธ๋ฆฌ ์ž…๋ ฅํ•ด ๋†“๊ธฐ
    entry.insert( index, string ) : ์ฃผ์–ด์ง„ ์ธ๋ฑ์Šค์— ๋ฌธ์ž์—ด์„ ์‚ฝ์ž…
    • index : ์ปค์„œ์˜ ์œ„์น˜
      • 0 : ์—”ํŠธ๋ฆฌ ์‹œ์ž‘ ๋ถ€๋ถ„(๋งจ ์•ž)์— ๋ฌธ์ž์—ด ์‚ฝ์ž…
      • END : ์ž…๋ ฅ ํ•„๋“œ ์•ˆ์˜ ๋งจ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ƒ์ˆ˜
    • string : ์‚ฝ์ž…ํ•˜๋ ค๋Š” ๋ฌธ์ž์—ด
  • add ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด data.txt ํŒŒ์ผ์— ์ž…๋ ฅํ•œ ์ •๋ณด๋“ค์„ ์ €์žฅํ•˜๊ธฐ
    entry.get( ) : ํ•ด๋‹น ์—”ํŠธ๋ฆฌ ํ•„๋“œ์˜ ์ปจํ…์ธ ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜
  • add ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ  ๋‚˜๋ฉด, ์ž…๋ ฅ ํ•„๋“œ์— ์žˆ๋˜ ๊ฒƒ๋“ค์„ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ
    entry.delete( first, last=None ) : ์ฃผ์–ด์ง„ ๋ฒ”์œ„์˜ ๋ฌธ์ž๋“ค์„ ์‚ญ์ œ
    • first : ๋ฒ”์œ„์˜ ์‹œ์ž‘
    • last : ๋ฒ”์œ„์˜ ๋์œผ๋กœ, ์ƒ๋žต ์‹œ ๋ฌธ์ž ํ•˜๋‚˜๋งŒ ์ง€์›Œ์ง

โŒจ๏ธ main.py

from tkinter import *

# ---------------------------- SAVE PASSWORD ------------------------------- #
def save():
    website = website_entry.get()
    email = email_entry.get()
    password = password_entry.get()

    with open("data.txt", 'a') as data_file:
        data_file.write(f"{website}  |  {email}  |  {password}\n")
        website_entry.delete(0, END)
        password_entry.delete(0, END)

# ---------------------------- UI SETUP ------------------------------- #
โ€ฆ
add_button = Button(text="Add", width=36, command=save)
โ€ฆ

๐Ÿ“„ data.txt

Amazon  |  example@gmail.com  |  123456
Facebook  |  example@gmail.com  |  Qwerty
Google  |  example@gmail.com  |  Zxcvbn

4. ๋ฉ”์‹œ์ง€ ๋ฐ•์Šค์™€ ํŒ์—…์ฐฝ

๐Ÿ” ์œ ์˜ ์‚ฌํ•ญ

  • ์‚ฌ์šฉ์ž๊ฐ€ Add๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ, ๊ทธ๋ƒฅ ์ €์žฅ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์„ธ๋ถ€์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค
  • Tkinter ํŒ์—…์ฐฝ(standard diglogs)์˜ ๋ฉ”์‹œ์ง€ ๋ฐ•์Šค(message boxes)
    (ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— *๋กœ tkinter๋ฅผ ์ž„ํฌํŠธํ–ˆ์–ด๋„ ๋”ฐ๋กœ ์ž„ํฌํŠธ ํ•ด์•ผ ํ•จ)
    • messeagebox.showinfo( title=text, message=text, **optionsโ€ฆ )
    • messeagebox.showwarning( title=text, message=text, **optionsโ€ฆ )
    • messeagebox.showerror( title=text, message=text, **optionsโ€ฆ )
    • messeagebox.askquestion( title=text, message=text, **optionsโ€ฆ )
    • messeagebox.askokcancel( title=text, message=text, **optionsโ€ฆ )
    • messeagebox.askretrycalcel( title=text, message=text, **optionsโ€ฆ )
  • ์‚ฌ์šฉ์ž๊ฐ€ Add๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ, ์›น์‚ฌ์ดํŠธ๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋ฏธ์ž‘์„ฑ๋๋‹ค๋ฉด ์ด๋ฅผ ์•Œ๋ ค์•ผ ํ•œ๋‹ค
    • ์›น์‚ฌ์ดํŠธ๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„๋“œ์— ์ž‘์„ฑํ•œ ์ฝ˜ํ…์ธ ์˜ ๊ธธ์ด๊ฐ€ 0์ผ ๋•Œ๋ฅผ ์˜๋ฏธ

โŒจ๏ธ main.py

from tkinter import *
from tkinter import messagebox

# ---------------------------- SAVE PASSWORD ------------------------------- #
def save():
    website = website_entry.get()
    email = email_entry.get()
    password = password_entry.get()

    # ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•˜๋Š” ๋ฉ”์‹œ์ง€ ๋ฐ•์Šค
    if len(website) == 0 or len(password) == 0:
        messagebox.showwarning(message="Please make sure "
                                       "you haven't left any fields empty.")
    else:
        # ์ž…๋ ฅํ•œ ์ •๋ณด๋ฅผ ๋‹ค์‹œ ํ™•์ธ ํ›„, ok๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ €์žฅํ•˜๊ณ  calcel์„ ๋ˆ„๋ฅด๋ฉด ์ทจ์†Œํ•˜๋Š” ๋ฉ”์‹œ์ง€ ๋ฐ•์Šค
        is_ok = messagebox.askokcancel(title=website,
                                       message=f"these are the details entered:\n"
                                               f"Email: {email}\nPassword: {password}\n"
                                               f"Is it ok to save?")
        if is_ok:
            with open("data.txt", 'a') as data_file:
                data_file.write(f"{website}  |  {email}  |  {password}\n")
                website_entry.delete(0, END)
                password_entry.delete(0, END)

# ---------------------------- UI SETUP ------------------------------- #
โ€ฆ
add_button = Button(text="Add", width=36, command=save)
โ€ฆ
  • ํ•ด๋‹น Mac OS์—์„œ title์€ ์ถœ๋ ฅ ์•ˆ๋จ
  • ์ •๋ ฌ, ํฐํŠธ, ์ฐฝ ํฌ๊ธฐ ๋“ฑ ๋””ํ…Œ์ผํ•œ ์„ค์ •์€ ๋ฉ”์‹œ์ง€ ๋ฐ•์Šค์—์„œ ๋ถˆ๊ฐ€๋Šฅ

5. ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌํ•˜๊ธฐ

๐Ÿ” ์œ ์˜ ์‚ฌํ•ญ

  • ๐Ÿ—‚๏ธ Day5 ํ”„๋กœ์ ํŠธ : ๋น„๋ฐ€๋ฒˆํ˜ธ ์ƒ์„ฑ๊ธฐ ์ฝ”๋“œ ์žฌํ™œ์šฉ ๋ฐ ์ˆ˜์ •
    • ์›ํ•˜๋Š” ์ž๋ฆฌ์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๋Œ€์‹  ์ง€์ •
      (๋ฌธ์ž : 8 - 10์ž๋ฆฌ, ๊ธฐํ˜ธ : 2 - 4์ž๋ฆฌ, ์ˆซ์ž : 2 - 4์ž๋ฆฌ)
    • ๋ฆฌ์ŠคํŠธ ์ปดํ”„๋ฆฌํ—จ์…˜์œผ๋กœ ์ฝ”๋“œ ๋‹จ์ถ•
    • string.join( iterable ) : ์‹œํ€€์Šค์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ string์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ด์€ ์ƒˆ ๋ฌธ์ž์—ด ์ƒ์„ฑ
      • ์›์†Œ๋“ค์„ ๋นˆ ์นธ ์—†์ด ํ•˜๋‚˜๋กœ ๊ฒฐํ•ฉํ•˜๋ ค๋ฉด string ์ž๋ฆฌ์— ๋นˆ ๋ฌธ์ž์—ด ์ž…๋ ฅ
  • Generate Password ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด, Password ํ•„๋“œ์— ์ž๋™ ์ƒ์„ฑ๋˜๋„๋ก ๋ณ€๊ฒฝ
  • pyperclip (pypi ๋งํฌ)
    • ๊ธฐ๋Šฅ1 : ํด๋ฆฝ๋ณด๋“œ์— ์ง€์ •ํ•œ ํ…์ŠคํŠธ๋ฅผ ๋ฐ”๋กœ ๋ณต์‚ฌ
    • ๊ธฐ๋Šฅ2 : ํด๋ฆฝ๋ณด๋“œ์˜ ๋‚ด์šฉ์„ ๋ฐ”๋กœ ๋ถ™์—ฌ๋„ฃ๊ธฐ

โŒจ๏ธ main.py

from tkinter import *
from tkinter import messagebox
from random import choice, randint, shuffle
import pyperclip

# ---------------------------- PASSWORD GENERATOR ------------------------------- #
def generate_password():
    # ์ด๋ฏธ ์ƒ์„ฑ๋œ ํŒจ์Šค์›Œ๋“œ๊ฐ€ ์žˆ๋Š” ์ƒํƒœ์—์„œ ๋˜ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๊ฒฝ์šฐ ํŒจ์Šค์›Œ๋“œ ์—”ํŠธ๋ฆฌ ๋น„์šฐ๊ธฐ
    password_entry.delete(0, END)
    
    # Day5 ์ฝ”๋“œ ์žฌํ™œ์šฉ ๋ฐ ์ˆ˜์ •
    letters = [
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
        'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
        'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    ]
    numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']

    password_list = [choice(letters) for _ in range(randint(8, 10))]
    password_list += [choice(symbols) for _ in range(randint(2, 4))]
    password_list += [choice(numbers) for _ in range(randint(2, 4))]

    shuffle(password_list)

    password = "".join(password_list)
    password_entry.insert(0, password)
    pyperclip.copy(password)
# ---------------------------- SAVE PASSWORD ------------------------------- #
def save():
    website = website_entry.get()
    email = email_entry.get()
    password = password_entry.get()

    if len(website) == 0 or len(password) == 0:
        messagebox.showwarning(message="Please make sure "
                                       "you haven't left any fields empty.")
    else:
        is_ok = messagebox.askokcancel(title=website,
                                       message=f"these are the details entered:\n"
                                               f"Email: {email}\nPassword: {password}\n"
                                               f"Is it ok to save?")
        if is_ok:
            with open("data.txt", 'a') as data_file:
                data_file.write(f"{website}  |  {email}  |  {password}\n")
                website_entry.delete(0, END)
                password_entry.delete(0, END)

# ---------------------------- UI SETUP ------------------------------- #
window = Tk()
window.title("Passwork Manager")
window.config(padx=50, pady=50)

canvas = Canvas(width=200, height=200)
logo_img = PhotoImage(file="logo.png")
canvas.create_image(130, 100, image=logo_img)
canvas.grid(row=0, column=1)

website_label = Label(text="Website:")
website_label.grid(row=1, column=0)
email_label = Label(text="Email/Username:")
email_label.grid(row=2, column=0)
password_label = Label(text="Password:")
password_label.grid(row=3, column=0)

website_entry = Entry(width=38)
website_entry.grid(row=1, column=1, columnspan=2)
website_entry.focus()
email_entry = Entry(width=38)
email_entry.grid(row=2, column=1, columnspan=2)
email_entry.insert(0, "example@gmail.com")
password_entry = Entry(width=21)
password_entry.grid(row=3, column=1)

generate_password_button = Button(text="Generate Password", command=generate_password)
generate_password_button.grid(row=3, column=2)
add_button = Button(text="Add", width=36, command=save)
add_button.grid(row=4, column=1, columnspan=2)


window.mainloop()




โ–ท Angela Yu, [Python ๋ถ€ํŠธ์บ ํ”„ : 100๊ฐœ์˜ ํ”„๋กœ์ ํŠธ๋กœ Python ๊ฐœ๋ฐœ ์™„์ „ ์ •๋ณต], Udemy, https://www.udemy.com/course/best-100-days-python/?couponCode=ST3MT72524

0๊ฐœ์˜ ๋Œ“๊ธ€