Python | tkinter를 이용한 파이썬 GUI

Stellar·2023년 11월 1일
0

Python

목록 보기
27/36
post-custom-banner

tkinter를 이용한 GUI 파이썬 프로그래밍

✔️ tkinter 실행하기

from tkinter import *

window = Tk() #Tk 클래스 불러오기.

label = Label(window, text = 'Hello world! :)')
label.pack() #창 크기 글자에 맞게 자동 조정

window.mainloop() #윈도우 프로세스에 넣어주는 기능.

✔️ 버튼과 이벤트처리.

from tkinter import *

#이벤트
def callback() :
    b1['text'] = '버튼이 클릭 됨.'

#tkinter 클래스 정의.
window = Tk()

#label
label = Label(window, text = 'Wellcome!')

label.pack(pady=30)

#Button
b1 = Button(window, text = '누르지 마시오.', command = callback) #함수 callback을 호출
b2 = Button(window, text = '누르시오.')
b3 = Button(window, text = 'button-3')
b4 = Button(window, text = 'button-4')

#위치할 순서. pack을 삭제하니 객체가 사라짐.
#pad = padding, x와 y축을 설정한다.
b4.pack()
b1.pack(side=LEFT, padx=10, pady = 20)
b2.pack(side=RIGHT, padx=10)
b3.pack(pady=20)

#버튼 내용 수정하기.
b1['text'] = 'one'
b2['text'] = 'two'

window.mainloop()

❗️ 프로젝트 아이디어

버튼을 계속해서 누르면 이미지가 나와 쨰려보고 욕하고 누르지 말라하고 들어가는 모션. 누르지 마시오를 누르면 누르시오랑 버튼 글자가 바뀌도록 하기.

✔️ 클래스 사용 예제

기본 내용은 앱을 실행할 때 초기 상태로 맞춰야 하므로 초기화 함수에 넣어둔다.

from tkinter import *

class App :
    def __init__(self) :
        window = Tk()
        helloB = Button(window, text = 'Hello', command = self.hello, fg = 'red') #fg 글자색, bg 배경색.
        helloB.pack(side = LEFT)
        quitB = Button(window, text = 'Quit', command = self.quit, bg = 'yellow')
        quitB.pack(side = LEFT)
        window.mainloop()

    def hello(self) :
        print('Hello 버튼이 클릭되었음!')

    def quit(self) :
        print('Quit 버튼이 클릭되었음!')

App()

✔️ 글자, 배경색 바꾸는 방법.

from tkinter import *

window = Tk()

button = Button(window, text = 'Hello')
#버튼 내부에서 색상 옵션 지정
#fg 글자색, bg 배경색.
button2 = Button(window, text = 'Bye', fg = 'white', bg = 'skyblue') 

button.pack()
button2.pack()

#색상 별도 지정
button['fg'] = 'purple'
button['bg'] = 'yellow'

✔️ 크기 조절

import tkinter as tk
import tkinter.font as font

class App :
    def __init__(self) :
        root=tk.Tk()

        self.customFont = font.Font(family='Gothic', size=12)

        buttonframe = tk.Frame()
        label = tk.Label(root, text = 'Hello, World!', font = self.customFont)
                         
        buttonframe.pack()
        label.pack()
                         
        bigger = tk.Button(root, text = '폰트를 크게', command=self.BigFont)
        smaller = tk.Button(root, text = '폰트를 작게', command=self.SmallFont)

        bigger.pack()
        smaller.pack()
        root.mainloop()

    def BigFont(self) :
        size = self.customFont['size']
        #크기 조절 기능
        self.customFont.configure(size=size+2)

    def SmallFont(self) :
        size = self.customFont['size']
        self.customFont.configure(size=size-2)

app = App()

✔️ 색상 표를 불러와 고른 색상의 RGB와 색상 번호를 알 수 있다.

import tkinter.colorchooser

color = tkinter.colorchooser.askcolor()
print(color)

✔️ 체크 박스

choice = intvar() 선택이 가능한 기능
기능은 같고 값만 달라야 번호를 하나만 선택 할 수 있음.

다중 체크 박스

# 다중 선택 상자
from tkinter import *

window = Tk()
Label(window, text = '선호하는 언어를 모두 선택 하시오.').grid(row=0, sticky=W)

value1 = IntVar()
Checkbutton(window, text = 'Python', variable = value1).grid(row=1, sticky=W)
value2 = IntVar()
Checkbutton(window, text = 'C', variable = value2).grid(row=2, sticky=W)
value3 = IntVar()
Checkbutton(window, text = 'Java', variable = value3).grid(row=3, sticky=W)
value4 = IntVar()
Checkbutton(window, text = 'Javascript', variable = value4).grid(row=4, sticky=W)

mainloop()

✔️ sticky란

sticky=W 어딘가에 스티커처럼 붙인다. W(Western)는 왼쪽을 의미. Western
체크 박스가 왼쪽으로 가는 줄 알았는데, 행 자체가 움직임.

✔️ 리스트 박스

목록을 누르면 색상이 표시되면서 선택 됨.

from tkinter import *

window = Tk()

lb = Listbox(window, height = 4) #한번에 보이는 건 4개만 보여주겠다. 이상일 경우 스크롤을 사용해야 함.
lb.pack()
lb.insert(END, 'Python')
lb.insert(END, 'C')
lb.insert(END, 'Java')
lb.insert(END, 'Javascript')

✔️ 스크롤 바

#스크롤 바
from tkinter import *

window = Tk()

#스크롤 바 기능
sb = Scrollbar(window, orient=VERTICAL)
sb.pack(side=RIGHT, fill = Y)

lb = Listbox(window, height = 4)
lb.pack()
lb.insert(END, 'Python')
lb.insert(END, 'C')
lb.insert(END, 'Java')
lb.insert(END, 'Javascript')
lb.insert(END, 'Swift')
lb.insert(END, 'C++')
lb.insert(END, 'C#')
lb.insert(END, 'Go')

#마우스 휠 뿐만 아니라 스크롤 위젯을 사용할 수 있게 만드는 기능
sb.configure(command=lb.yview)
lb.configure(yscrollcommand=sb.set)

pack()

✔️ 양 옆으로 꽉 채우기.

from tkinter import *

window = Tk()

w = Label(window, text = 'Box #1', bg='red', fg='white')
w.pack(fill = X) # 하나씩 지정해줘야 기능 함.
w = Label(window, text = 'Box #2', bg='green', fg='white')
w.pack(fill = X)
w = Label(window, text = 'Box #3', bg='yellow')
w.pack(fill = X)
w = Label(window, text = 'Box #4', bg='blue', fg='white')
w.pack(fill = X)

window.mainloop()

배치 관리자

컨테이너 안에 존재하는 위젯의 크기와 위치를 자동적으로 관리하는 객체.

✔️ grid(), 격자 배치 관리자(grid geometry manager)

위젯(버튼, 레이블 등)을 테이블 형태로 배치.

from tkinter import *

window = Tk()

b1 = Button(window, text = 'One')
b2 = Button(window, text = 'Two')
b3 = Button(window, text = 'Three')
b4 = Button(window, text = 'Four')

#로우와 컬럼으로 배치하기.
b1.grid(row=0, column=0)
b2.grid(row=1, column=1)
b3.grid(row=3, column=1)
b4.grid(row=1, column=4) #컬럼 5로 하니 이전에 2,3,4가 없어 b2 버튼과 붙어서 나옴.

t1 = Label(window, text = '이것은 레이블입니다.')
t1.grid(row=1, column=3) #pack() 대신 grid() 사용.

window.mainloop()

grid 예제. color 판 만들기

#grid 연습
from tkinter import *

window = Tk()
colors = ['green', 'purple', 'yellow', 'blue', 'gold', 'white']

r = 0
for c in colors :
    Label(window, text = c, relief = RIDGE, width = 15).grid(row=r, column = 0)
    Button(window, bg = c, width = 10 ).grid(row=r, column =1)
    r += 1

window.mainloop()

✔️ .pack(), 압축 배치 관리자

grid처럼 별도의 row를 지정하지 않아도 순서대로 나옴.

from tkinter import *

window = Tk()

Label(window, text = 'Box #1', bg='red', fg='white').pack()
Label(window, text = 'Box #2', bg='green', fg='white').pack()
Label(window, text = 'Box #3', bg='yellow').pack()
Label(window, text = 'Box #4', bg='blue', fg='white').pack()

window.mainloop()

✔️ .pack(), 수평 정렬

from tkinter import *

window = Tk()

w = Label(window, text = 'Box #1', bg='red', fg='white')
w.pack(padx = 5, pady = 0, side = LEFT) # 하나씩 지정해줘야 기능 함.
w = Label(window, text = 'Box #2', bg='green', fg='white')
w.pack(padx = 5, pady = 0, side = LEFT)
w = Label(window, text = 'Box #3', bg='yellow')
w.pack(padx = 5, pady = 0, side = LEFT)
w = Label(window, text = 'Box #4', bg='blue', fg='white')
w.pack(padx = 5, pady = 0, side = LEFT)

window.mainloop()

✔️ .place(), 절대 위치 관리자

from tkinter import *

window = Tk()

w = Label(window, text = 'Box #1', bg='red', fg='white')
w.place(x = 0, y = 0)
w = Label(window, text = 'Box #2', bg='green', fg='white')
w.place(x = 30, y = 20)
w = Label(window, text = 'Box #3', bg='yellow')
w.place(x = 60, y = 40)
w = Label(window, text = 'Box #4', bg='blue', fg='white')
w.place(x = 90, y = 60)

window.mainloop()

✔️ Frame()

#혼합 사용
from tkinter import *

window = Tk()
f = Frame(window)

b1 = Button(f, text = 'One')
b2 = Button(f, text = 'Two')
b3 = Button(f, text = 'Three')

b1.pack(side = LEFT)
b2.pack(side = LEFT)
b3.pack(side = LEFT)

l = Label(window, text = '이 레이블은 버튼들 위에 배치 됨.')

#객체들의 순서.
l.pack()
f.pack()


window.mainloop()

종합예제

✔️ 종합 예제. 게임 만들기 Tic-Tac-Toe

#게임 만들기 예제. Tic-Tac-Toe
from tkinter import *

# i번째 버튼을 누를 수 있는지 검사한다. 누를 수 있으면 X나 O를 표시.
def checked(i) :
    global player
    button = list[i] #리스트에서 i번째 버튼 객체를 가져 옴.

    #버튼이 초기 상태가 아니면 이미 누른 버튼이므로 아무것도 하지 않고 리턴.
    #스페이스를 주어 버튼의 칸을 늘린다.
    if button['text'] != '        ' :
        return
    button['text'] = '   ' + player + '   ' 
    button['bg'] = 'yellow'
    if player == 'X' :
        player = '0'
    else :
        player = 'X'
        button['bg'] = 'lightgreen'

window = Tk() #윈도우 생성
player = 'X' #시작은 플레이어 X
list = []

# 9개의 버튼을 생성, 격자 형태로 윈도우에 배치.
for i in range(9) :
    b = Button(window, text='        ', command = lambda k=i : checked(k))
    b.grid(row=i//3, column=i%3)
    list.append(b) #버튼 객체를 리스트에 저장.

window.mainloop()

✔️ 종합 예제2. 스톱워치 만들기

import tkinter as tk

def startTimer():
    if running :
        global timer
        timer += 1
        timeText.configure(text=str(timer))
    window.after(10, startTimer)

def start() :
    global running
    running = True

def stop() :
    global running
    running = False

running = False

window = tk.Tk()

timer = 0

timeText = tk.Label(window, text='0', font = ('Helvetica', 80))
timeText.pack()

startButton = tk.Button(window, text='시작', bg='yellow', command=start)
startButton.pack(fill = tk.BOTH)

stopButton = tk.Button(window, text='중지', bg='yellow', command=stop)
stopButton.pack(fill = tk.BOTH)

startTimer()
window.mainloop()

✔️ 종합 예제3. 계산기 만들기

아래 코드에서 사용된 eval() 함수는 문자열인 수식도 알아서 계산식으로 바꿔준다. 하지만 접근 불허한 디렉토리도 접근이 가능해 보안에 아주 취약하다. 또한 의존성을 주어 코드에 악영향을 미치므로 되도록 사용하지 말아야한다.
python eval() 함수 - 사용을 조심해야 하는 이유

#계산기 만들기
from tkinter import *

#비즈니스 로직
def click(key):
    if key == '=' :
        try :
            result = eval(entry.get())
            entry.delete(0, END)
            entry.insert(END, str(result))
        except:
            entry.insert(END, '오류!')
    elif key == 'C' :
        entry.delete(0, END)
    else:
        entry.insert(END, key)

#그래픽 디자인
window = Tk()
window.title('간단한 계산기')

buttons = [
'7', '8', '9', '+', 'C',
'4', '5', '6', '-', ' ',
'1', '2', '3', '*', ' ',
'0', '.', '=', '/', ' ' ]

#반복문으로 버튼 생성.
i = 0
for b in buttons :
    cmd = lambda x = b: click(x)
    b = Button(window, text=b, width=5, relief='ridge', command=cmd)
    b.grid(row=i // 5 +1, column=i % 5)
    i += 1

# 엔트리 위젯은 맨 윗줄의 5개의 셀에 걸쳐서 배치
entry = Entry(window, width = 33, bg='yellow')
entry.grid(row=0, column=0, columnspan=5) #columnspan=5는 5개의 컬럼을 전체적으로 적용하겠다는 말.

window.mainloop()

이벤트 처리

기본 문법

위젯.bind(이벤트 지정자, 이벤트 처리 함수)

✔️ 마우스 및 키보드 클릭 이벤트

frame.bind('<Button-1>', callback) Button-1은 우클릭, 2 = 휠 클릭, 3 = 좌 클릭을 뜻 함.
마우스를 먼저 클릭해야만 키보드 클릭이 됨.

from tkinter import *

window = Tk()

def key(event) :
    print(repr(event.char), '가 눌렸습니다.')

def callback(event) :
    frame.focus_set()
    print(event.x, event.y, '에서 마우스 이벤트 발생.')

frame = Frame(window, width = 100, height = 100)
frame.bind('<Key>', key)
frame.bind('<Button-3>', callback)
frame.pack()

window.mainloop()

✔️ 마우스 드래그 이벤트. 클릭 후 드래그.

클릭과 코드는 같지만 bind에 을 넣어 줌.
마우스 클릭 방향은 공통이다. 1-우클릭, 2-휠클릭, 3-좌클릭

from tkinter import *

window = Tk()

def callback(event) :
    print(event.x, event.y, '에서 마우스 이벤트 발생.')

frame = Frame(window, width = 100, height = 100)
frame.bind('<B3-Motion>', callback)
frame.pack()

window.mainloop()

✔️ 마우스 드래그 이벤트2. 움직이기만 해도 된다.

from tkinter import *

def motion(event) :
    print('마우스 위치: (%s, %s)' % (event.x, event.y))
    return
    
window = Tk()

message = '''당신 스스로가 하지 않으면
아무도 당신의 운명을
개선시켜주지 않을 것이다.'''

msg = Message(window, text = message)
msg.configure( fg ='white', font='times 20 italic')
msg.bind('<Motion>', motion)

msg.pack()

window.mainloop()

✔️ 숫자 맞추기 게임

from tkinter import *
import random

answer = random.randint(1, 100)

def guessing() :
    guess = int(guessField.get())

    if guess > answer :
        msg = '정답보다 값이 큼!'
    elif guess < answer :
        msg = '정답보다 값이 작음!'
    else :
        msg = '정답!'

    resultLabel['text'] = msg
    guessField.delete(0, 5)

def reset() :
    global answer
    answer = random.randint(1, 100)
    resultLabel['text'] = '다시 한번 하세요!'

window = Tk()
window.configure(bg='white')
window.title('숫자 맞추기 게임')
window.geometry('500x80')

titleLabel = Label(window, text = '숫자 게임에 오신 것을 환영합니다.!', bg='white')
titleLabel.pack()

guessField = Entry(window)
guessField.pack(side='left')
tryButton = Button(window, text = '시도', fg = 'green', bg = 'white', command=guessing)
tryButton.pack(side = 'left')

resetButton = Button(window, text = '초기화', fg = 'red', bg = 'white', command=reset)
resetButton.pack(side = 'left')
resultLabel = Label(window, text = '1부터 100사이의 숫자를 입력하시오.', bg = 'white')
resultLabel.pack(side = 'left')

window.mainloop()

✔️ ID,PW 입력창 만들기.

from tkinter import *

def print_fields() :
    print('ID: %s\nPW: %s' % (e1.get(), e2.get()))

window = Tk()
Label(window, text='ID').grid(row=0)
Label(window, text='PW').grid(row=1)

e1 = Entry(window)
e2 = Entry(window)

e1.grid(row=0, column=1)
e2.grid(row=1, column=1)

Button(window, text='Login', command=print_fields).grid(row=3, column=0, sticky=W, pady=4)
Button(window, text='Cancle', command=window.quit).grid(row=3, column=1, sticky=W, pady=4)
          
window.mainloop()
post-custom-banner

0개의 댓글