✨ 이번 챕터를 수행하기 위해서는 파이썬을 미리 설치해두어야 한다!
📒 요약 : 사용자는 텍스트 형태로 된 프로그램보다 GUI를 이용한 편리한 환경에서 데이터베이스를 사용하는 것을 선호한다. 이러한 환경을 제공하는 GUI 프로그램에 대해 알아보자.
GUI는 왼도에 그래픽 환경으로 제공되는 화면이다. 파이썬으로 윈도우에 출력되는 GUI 응용 프로그램을 작성할 수 있는데, tkinter 라이브러리를 활용해보자. tkinter를 활용하면 흔히 사용하는 엑셀, 한글, 크롬 등의 응용 프로그램과 비슷한 형태의 프로그램을 만들 수 있다. 그리고 sql을 전혀 모르는 사용자도 마우스 클릭만으로 데이터 입력, 조회가 가능하도록 할 수 있다.
파이썬과 MySQL 데이터베이스를 연동해보자. 연동 프로그램이 완성되면 MySQL 워크벤치가 없어도 MySQL에 접근하고 사용할 수 있다.
GUI의 가장 기본적인 윈도우 화면이다. 아래는 가장 간단한, 아무것도 출력하지 않는 윈도우를 나타내는 코드이다.
#tkinter 임포트하기
from tkinter import *
#TK() : 루트 윈도우
root = Tk()
#윈도우의 제목 표시
root.title("혼공GUI 연습")
#윈도우의 초기 크기 설정
root.geometry("400*200")
#윈도우에 키보드 누르기, 마우스 클릭 등 다양한 작업이 일어날 때 이벤트를 처리하기 위해 필요한 부분
root.mainloop()
그림1. tkinter의 기본 윈도우
라벨은 문자를 표현할 수 있는 위젯으로, label(부모윈도, 옵션) 형식을 사용한다. 위젯은 윈도우에 나오는 버튼, 텍스트, 라디오 버튼, 이미지 등을 통합해서 지칭하는 용어이다. 옵션에서 모양에 대한 다양한 설정을 할 수 있으며, 모든 위젯들은 pack()함수를 사용해야 화면에 출력된다. 아래는 간단한 라벨을 출력하는 예시이다.
from tkinter import *
root = Tk()
root.geometry("300x100")
#Label 함수로 라벨을 만든다. fg, bg 옵션으로 글자색과 배겨경색을 지정한다.
label1 = Label(root, text="혼공 SQL은")
label2 = Label(root, text="쉽습니다.", font=("궁서체", 30), bg="blue", fg="yellow")
#pack()함수로 해당 라벨을 화면에 표시해준다.
label1.pack()
label2.pack()
root.mainloop()
그림2. tkinter의 라벨
버튼은 마우스로 클릭하면 지정한 작업이 실행되도록 사용되는 위젯으로, Button(부모윈도우, 옵션) 형식을 사용한다. GUI에서 활용도가 높은 위젯이다. 버튼은 command 옵션으로 사용자가 버튼을 눌렀을 때 지정한 작업을 처리해야 한다는 점이 라벨과 조금 다르다. 아래의 코드는 버튼을 누르면 메시지 상자가 출력되는 코드이다.
from tkinter import *
from tkinter import messagebox
def clickButton() :
messagebox.showinfo('버튼 클릭', '버튼을 눌렀습니다..')
root = Tk()
root.geometry("200x200")
#command 옵션에 clickButton()함수를 호출한다. 버튼을 클릭하면 메시지 상자가 나타난다.
button1 = Button(root, text="여기를 클릭하세요", fg="red", bg="yellow", command=clickButton)
#pack()에서 버튼을 화면 중앙에 표현하기 위해 expand=1 옵션을 추가한다.
button1.pack(expand = 1)
root.mainloop()
그림3. tkinter의 버튼
pack() 함수의 옵션 중에서 가로로 정렬하는 방법으로 side=LEFT 또는 RIGHT 방식이 있다. side=LEFT 옵션은 왼쪽부터 채워나가라는 의미이다. LEFT를 모두 RIGHT로 바꾸면 오른쪽부터 나온다.
side=TOP 또는 BOTTOM 방식을 사용하면 수직으로 정렬할 수 있다. 정렬하는 방법은 LEFT/RIGHT와 같다.
from tkinter import *
root = Tk()
button1 = Button(root, text="혼공1")
button2 = Button(root, text="혼공2")
button3 = Button(root, text="혼공3")
button1.pack(side=LEFT)
button2.pack(side=LEFT)
button3.pack(side=LEFT)
root.mainloop()
그림4. tkinter의 위젯 정렬하기
프레임은 화면을 여러 구역으로 나눌 때 사용한다. 엔트리는 입력 상자를 표현하고, 리스트 박스는 목록을 표현한다. 아래의 코드를 통해 살펴보자.
from tkinter import *
root = Tk()
root.geometry("200x250")
#upFrame 및 downFrame이라는 2개의 프레임을 생성하고 화면에 출력한다. 프레임은 구역을 나눈 것일 뿐 화면에 표시되지는 않는다.
upFrame = Frame(root)
upFrame.pack()
downFrame = Frame(root)
downFrame.pack()
#입력을 위한 엔트리. root윈도우 대신 upFrame에 나오도록 설정한다.
editBox = Entry(upFrame, width = 10, )
editBox.pack(padx = 20, pady = 20)
#리스트 박스. 리스트박스는 아래쪽인 downFrame에 나오도록 설정한다.
listbox = Listbox(downFrame, bg = 'yellow');
listbox.pack()
#리스트 박스에 데이터를 3건 입력한다. 옵션 중 END는 데이터를 제일 뒤에 첨부하라는 의미이다.
listbox.insert(END, "하나")
listbox.insert(END, "둘")
listbox.insert(END, "셋")
root.mainloop()
그림5. tkinter의 프레임, 엔트리, 리스트 박스 구성하기
지금까지 배운 내용으로 SQL과 연동하는 응용 프로그램을 만들어보자. 여기서는 GUI 화면에서 데이터의 입력과 수정이 가능하도록 만들었다. 그리고 초기화 버튼을 클릭하면 테이블이 삭제되고 다시 생성된다.
import pymysql
from tkinter import *
from tkinter import messagebox
## 메인 코드부
def insertData() :
con, cur = None, None
data1, data2, data3, data4 = "", "", "", ""
sql=""
conn = pymysql.connect(host='127.0.0.1', user='root', password='0000', db='soloDB', charset='utf8')
cur = conn.cursor()
data1 = edt1.get(); data2 = edt2.get(); data3 = edt3.get(); data4 = edt4.get()
sql = "INSERT INTO userTable VALUES('" + data1 + "','" + data2 + "','" + data3 + "'," + data4 + ")"
cur.execute(sql)
conn.commit()
conn.close()
messagebox.showinfo('성공', '데이터 입력 성공')
def selectData() :
strData1, strData2, strData3, strData4 = [], [], [], []
conn = pymysql.connect(host='127.0.0.1', user='root', password='0000', db='soloDB', charset='utf8')
cur = conn.cursor()
cur.execute("SELECT * FROM userTable")
strData1.append("사용자 ID"); strData2.append("사용자 이름")
strData3.append("사용자 이메일"); strData4.append("사용자 출생연도")
strData1.append("-----------"); strData2.append("-----------")
strData3.append("-----------"); strData4.append("-----------")
while (True) :
row = cur.fetchone()
if row== None :
break;
strData1.append(row[0]); strData2.append(row[1])
strData3.append(row[2]); strData4.append(row[3])
listData1.delete(0,listData1.size() - 1); listData2.delete(0,listData2.size() - 1)
listData3.delete(0,listData3.size() - 1); listData4.delete(0,listData4.size() - 1)
for item1, item2, item3, item4 in zip(strData1, strData2, strData3, strData4 ):
listData1.insert(END, item1); listData2.insert(END, item2)
listData3.insert(END, item3); listData4.insert(END, item4)
conn.close()
## 메인 코드부
root = Tk()
root.geometry("600x300")
root.title("완전한 GUI 응용 프로그램")
edtFrame = Frame(root);
edtFrame.pack()
listFrame = Frame(root)
listFrame.pack(side = BOTTOM,fill=BOTH, expand=1)
edt1= Entry(edtFrame, width=10); edt1.pack(side=LEFT,padx=10,pady=10)
edt2= Entry(edtFrame, width=10); edt2.pack(side=LEFT,padx=10,pady=10)
edt3= Entry(edtFrame, width=10); edt3.pack(side=LEFT,padx=10,pady=10)
edt4= Entry(edtFrame, width=10); edt4.pack(side=LEFT,padx=10,pady=10)
btnInsert = Button(edtFrame, text="입력", command = insertData)
btnInsert.pack(side=LEFT,padx=10,pady=10)
btnSelect = Button(edtFrame, text="조회", command =selectData )
btnSelect.pack(side=LEFT,padx=10,pady=10)
listData1 = Listbox(listFrame,bg = 'yellow');
listData1.pack(side=LEFT,fill=BOTH, expand=1)
listData2 = Listbox(listFrame,bg = 'yellow')
listData2.pack(side=LEFT,fill=BOTH, expand=1)
listData3 = Listbox(listFrame,bg = 'yellow')
listData3.pack(side=LEFT,fill=BOTH, expand=1)
listData4 = Listbox(listFrame,bg = 'yellow')
listData4.pack(side=LEFT,fill=BOTH, expand=1)
root.mainloop()