경기도 인공지능 개발 과정/Python

[Python] tkinter를 이용한 GUI 개발

agingcurve 2022. 7. 10. 13:27
반응형
 

1. GUI란

  • UI : 사용자 인터페이스(User Interface) 사용자와 코드 사이를 연결하는 모든 것
  • GUI : Graphical User Interface, UI 중 시각적인 부분

 

< 지금까지 작성한 프로그램 형태 >

 

< 사용자화면(GUI)이 중간에 추가된 형태 >

Icons made by Freepik from www.flaticon.com

파이썬 표준 GUI, tkinter

python.org의 공식 tkinter 문서 , TkDocs Tutorial

2. tkinter 창 만들어 띄우기

from tkinter import *

root = Tk()
root.mainloop()
In [ ]:
from tkinter import * 
root = Tk()
root.mainloop() 
In [15]:
root = Tk()
root.title("my first tkinter")
root.mainloop()
# 창의 제목 표현하기
root.title('제목')

# 창의 크기 결정하기
root.geometry('가로길이x세로길이')
In [ ]:
root = Tk()
root.title('my first tkinter')
root.mainloop()
In [ ]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
root.mainloop()

3. 레이블 Label

화면에 표현할 수 있는 다양한 요소들

3-1. 텍스트 레이블

# 레이블 만들기
레이블이름 = Label(창이름, text='표현할 텍스트')

# 레이블 위치시키기
레이블이름.pack()
In [16]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='안녕하세요!')
root.mainloop()
In [ ]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='안녕하세요!') 
label1.pack()
root.mainloop()
In [5]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='Hello', font=('Malgun Gothic', 20), 
fg='blue', bg='gray', width= 20, height=5, anchor='se')
label1.pack() 
root.mainloop()

3-2. 이미지 레이블

  1. PhotoImage 클래스의 객체 만들기 (gif, png, pgm, ppm)
  2. Label 객체 생성시 image옵션 사용
In [ ]:
from tkinter import *
root = Tk()
root.title('my first tkinter')
root.geometry('800x400')
letsgetit = PhotoImage(file='lets get it.png') # 
img_label = Label(root, image=letsgetit)     # 
img_label.pack()
root.mainloop()
# Tcl 오류
TclError: image "pyimage4" doesn't exist

=> 해결책 : 커널 재실행(restart)

3-3. 위젯 배치하기

  • 절대위치 배치
    1. place(x= x좌표, y= y좌표)
  • 상대위치 배치
    1. pack() : 위젯들간의 상대적 위치로 위젯 배치
    2. grid() : 격자 한 칸에 위젯을 배치
In [ ]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='안녕하세요!', relief='groove')
label1.grid(row=0, column=0)
label2 = Label(root, text='Hello!', relief='groove')
label2.grid(row=0, column=1)
label3 = Label(root, text='니 하오!', relief='groove')
label3.grid(row=1, column=0)
label4 = Label(root, text='봉쥬르!', relief='groove')
label4.grid(row=1, column=1)
root.mainloop()
In [ ]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='안녕하세요!', relief='groove')
label1.grid(row=0, column=0)
label2 = Label(root, text='Hello!', relief='groove')
label2.grid(row=0, column=1)
label3 = Label(root, text='니 하오!', relief='groove')


# label3의 row를 1이 아닌 9로
label3.grid(row=9, column=0)
label4 = Label(root, text='봉쥬르!', relief='groove')

# label4의 row, column을 1이 아닌 9로

label4.grid(row=9, column=9)
root.mainloop()

grid()의 row와 column 숫자는 자동으로 앞에서부터 채워짐

In [ ]:
# 각 위젯의 너비, 높이를 설정하고 grid()로 배치하기
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='안녕하세요!', width=20, height=5, relief='groove')
label1.grid(row=0, column=0)
label2 = Label(root, text='Hello!', width=10, height=5, relief='groove')
label2.grid(row=0, column=1)
label3 = Label(root, text='니 하오!', width=10, height=5, relief='groove')
label3.grid(row=1, column=0)
label4 = Label(root, text='봉쥬르!', width=20, height=5, relief='groove')
label4.grid(row=1, column=1)
root.mainloop()

격자의 여러 칸 합치기

rowspan= 병합할 격자 개수  
columnspan= 병합할 격자 개수
In [ ]:
root = Tk()
root.title('my first tkinter')
root.geometry('400x200')
label1 = Label(root, text='안녕하세요!', width=15, relief='groove')
label1.grid(row=0, column=0)
label2 = Label(root, text='Hello!', width=15, relief='groove')
label2.grid(row=0, column=1)
label3 = Label(root, text='니 하오!', width=15, relief='groove')
label3.grid(row=1, column=0, columnspan=2)
label4 = Label(root, text='봉쥬르!', width=15, relief='groove')
label4.grid(row=0, column=2, rowspan=2)
root.mainloop()
In [ ]:
# 이미지와 텍스트 동시에 나타내기
root = Tk()
root.title('my first tkinter')
root.geometry('700x450')
label_txt = Label(root, text='파이썬 프로그래밍', font=('Malgun Gothic', 30))
label_txt.grid(row=0, column=0)
letsgetit = PhotoImage(file='lets get it.png')
label_img = Label(root, image=letsgetit)
label_img.grid(row=1, column=0)
root.mainloop()

4. 버튼 만들기

버튼이름 = Button(창이름, text='버튼에 표현할 텍스트')
In [ ]:
root = Tk()
root.title('Button')
root.geometry('400x200')
btn1 = Button(root, text='버튼', width=10, height=3)
btn1.pack()
root.mainloop()
root = Tk()
root.title('Button')
root.geometry('400x200')
lbl1 = Label(root, text='안녕하세요!', width=40)
lbl1.grid(row=0, column=0)
btn1 = Button(root, text='확인', width=10)
btn1.grid(row=0, column=1)
root.mainloop()
btn1.grid(row=0, column=1)
root.mainloop()

버튼을 클릭하면 실행할 이벤트 설정하기

def 함수이름 : 
    # 함수 정의 

버튼이름 = Button(창이름, text='버튼텍스트', command= 함수이름)
In [ ]:
def sayhello():
 print('Hello!! ' * 3)
root = Tk()
root.title('Button')
root.geometry('400x200')
lbl1 = Label(root, text='안녕하세요! ', width=40)
lbl1.grid(row=0, column=0)
btn1 = Button(root, text='확인', width=10, command=sayhello)
btn1.grid(row=0, column=1)
lbl2 = Label(root, text='Hello!! Hello!! Hello!! ')
lbl2.grid(row=1, column=0)
root.mainloop()
In [ ]:
# 버튼을 누르면 Hello 나타나게 하기

def sayhello():
 print('Hello!! ' * 3)
root = Tk()
root.title('Button')
root.geometry('400x200')
lbl1 = Label(root, text='안녕하세요! ', width=40)
lbl1.grid(row=0, column=0)
btn1 = Button(root, text='확인', width=10, command=sayhello)
btn1.grid(row=0, column=1)
lbl2 = Label(root, text='Hello!! Hello!! Hello!! ')
lbl2.grid(row=1, column=0)
root.mainloop()

동적변수

: 화면이 생성된 후에 변하는 값을 저장하는 변수

  1. 사용 전에 먼저 동적변수를 만들기
# 문자열 동적변수
변수이름 = StringVar()

# 정수형 동적변수 = IntVar()
# 실수형 동적변수 = DoubleVar()
  1. Label객체에 textvariable 옵션
레이블이름 = Label(창이름, textvariable= 동적변수이름)
  1. 동적변수의 값 변경하기
동적변수이름.set(변경값)
In [ ]:
# ----- 프로그램 기능 부분 -----

def sayhello():
 txt.set('Hello!! ' * 3) # sayhello() 함수 실행 시 동적변수 txt 에 값 넣기

# ----- 프로그램 화면 부분 -----

root = Tk()
root.title('Button')
root.geometry('400x200')
lbl1 = Label(root, text='안녕하세요! ', width=40)
lbl1.grid(row=0, column=0)
btn1 = Button(root, text='확인', width=10, command=sayhello)
btn1.grid(row=0, column=1)

# 동적변수 txt 정의
txt = StringVar()

# 레이블에 동적변수 txt 설정
lbl2 = Label(root, textvariable=txt, width=40, height=3)
lbl2.grid(row=1, column=0, columnspan=2)
root.mainloop()

구구단 프로그램 만들기

In [ ]:
import random
# 전역변수
num1, num2 = 0, 0
# 2. 버튼 클릭시 실행될 이벤트 작성
def make_question() :
 global num1, num2
 num1, num2 = random.randint(2, 9), random.randint(1, 9)
 question.set(str(num1)+'x'+str(num2)+'? ')

def check_answer() :
 answer.set(num1*num2)

# 1. tkinter 화면 구성
root = Tk()
root.title('구구단')
question = StringVar()
q_lbl = Label(root, textvariable= question, width=30)
q_lbl.grid(row=0, column=0)
q_btn = Button(root, text='새로운 문제', width=10, command=make_question)
q_btn.grid(row=0, column=1)
a_btn = Button(root, text='정답 확인', width=10, command=check_answer)
a_btn.grid(row=1, column=1)
answer = StringVar()
a_lbl = Label(root, textvariable= answer, width=30)
a_lbl.grid(row=1, column=0)
root.mainloop()

5. 엔트리

: 화면에서 값을 입력받을 수 있는 칸

엔트리이름 = Entry(창 이름)
In [ ]:
from tkinter import *
root = Tk()
root.title('entry')
root.geometry('400x200')
ent = Entry(root, width=25)
ent.grid(row=0, column=0)
root.mainloop()
root = Tk()
root.title('entry')
root.geometry('400x200')
lbl = Label(root, text='이름 : ' , width=10)
lbl.grid(row=0, column=0)
ent = Entry(root, width=25)
ent.grid(row=0, column=1)
root.mainloop()
In [ ]:

엔트리에 입력된 값을 읽어들이기

엔트리이름.get()
In [ ]:
def entry_value():
 print(ent.get()) # 함수 실행 시 get()으로 ent 의 값을 읽어 들여 출력함
root = Tk()
root.title('entry')
root.geometry('400x200')
lbl = Label(root, text='이름 : ' , width=10)
lbl.grid(row=0, column=0)
ent = Entry(root, width=25)
ent.grid(row=0, column=1)
btn = Button(root, text='확인', width=0, command=entry_value)
btn.grid(row=0, column=2)
root.mainloop()

6. 프레임



로그인 화면 만들기

In [ ]:
root = Tk()
root.title('frame')
root.geometry('400x200')
frame_A = Frame(root, relief='groove', borderwidth=2)
frame_A.grid(row=0, column=0)
frame_B = Frame(root, relief='groove', borderwidth=2)
frame_B.grid(row=1, column=0)
id_lbl = Label(frame_A, text='아이디 ',width=10, height=2)
id_lbl.grid(row=0, column=0)
id_ent = Entry(frame_A, width=20)
id_ent.grid(row=0, column=1)
pw_lbl = Label(frame_B, text='비밀번호', width=10, height=2)
pw_lbl.grid(row=0, column=0)
pw_ent = Entry(frame_B, width=20)
pw_ent.grid(row=0, column=1)
root.mainloop()