카테고리 없음
8. SQL과 파이썬 연결-3
다방황군
2022. 2. 24. 11:46
0. 학습 목표
- 파이썬을 설치하고 외부 라이브러리를 이해
- 파이썬과 MySQL을 연동하는 프로그램을 작성
- 윈도가 나오는 멋진 SQL 연동 프로그램을 만듬
0. 요약
- 파이썬에서 제공하지 않는 기능을 사용하기 위해서는 별도의 외부 라이브러리를 설치
- PyMySQL은 파이썬과 MySQL을 연결시켜주는 외부 라이브러리
- 파이썬은 대화형 모드와 한 번에 실행하는 스크립트 모드가 있음
- 데이터베이스 연동은 SQL을 파이썬과 연결하는 것
- import pymysql 명령을 사용해서 SQL과 파이썬을 연동
- pymysql,connect()로 연결자를 생성하고 커서를 통해 파이썬에서 MySQL로 SQL을 전송
- 데이터를 변경한 경우 commit을 수행해야 최종 반영
- 파이썬에서 SELECT 문으로 데이터를 조회한 후에는 fetchone()함수로 데이터를 한 행씩 가져옴
- tkinter는 파이썬에서 GUI를 만들기 위해 제공되는 라이브러리
- 라벨은 윈도에 문자를 표현하고 버튼은 클릭하는 기능을 제공
3. GUI 응용 프로그램
※핵심 키워드: GUI, thiner, 라벨, 버튼, 프레임, 엔트리, 리스트 박스
tkinter라는 라이브러리를 사용하면 엑셀, 크롬 등의 응용 프로그램과 비슷한 형태의 프로그램을 만들 수 있다. SQL을 전혀 모르는 사용자도 마우스 클릭만으로 데이터 입력, 조회가 가능하도록 할 수 있다.
3-1. GUI 기본 프로그래밍
기본 윈도의 구성
GUI의 가장 기본적인 윈도 화면의 구성을 살펴보자.
######### 1 #########
from tkinter import *
######### 1 #########
######### 2 #########
root = Tk()
######### 2 #########
######### 3 #########
root.mainloop()
######### 3 #########
- tkinter는 파이썬에서 GUI 관련 모듈을 제공해 주는 표준 윈도 라이브러리이다.
- Tk()는 기본이 되는 윈도를 반환하는데, 이를 root라는 변수에 넣었다. Tk()를 루트 윈도라고도 부르며 꼭 필요한 요소이다.
- root.mainloop() 함수를 실행한다. 다양한 작업이 일어날 때 이벤트를 처리하기 위해 필요한 부분이다.
이번에는 윈도 제목을 지정하고 크기를 설정해 보자.
from tkinter import *
root = Tk()
root.title("혼공 GUI 연습")
root.geometry("400x200")
root.mainloop()
라벨
라벨은 문자를 표현할 수 있는 위젯이다.
- label(부모윈도, 옵션 ...) 형식 사용
- widget은 윈도에 나오는 버튼 텍스트 라디오 버튼, 이미지 등을 통합해서 지칭하는 용어
- pack() 한수를 사용해야 화면에 나타남
from tkinter import *
root = Tk()
root.title("혼공 GUI 연습")
root.geometry("300x100")
label1 = Label(root, text="혼공 SQL은")
label2 = Label(root, text="쉽습니다.", font=("궁서체", 30), bg="blue", fg="yellow")
label1.pack()
label2.pack()
root.mainloop()
버튼
버튼은 마우스로 클릭하면 지정한 작업이 실행되도록 사용되는 위젯이다.
- Button(부모윈도, 옵션 ...) 형식 사용
- command 옵션으로 버튼을 눌렀을 때 지정한 작업을 처리
from tkinter import *
from tkinter import messagebox
def clickButton():
messagebox.showinfor('버튼 클릭', '버튼을 눌렀습니다..')
root = Tk()
root.title("혼공 GUI 연습")
root.geometry("200x200")
button1 = Button(root, text="여기를 클릭하세요", fg="red", bg="yellow", command=clickButton)
button1.pack(expand = 1)
root.mainloop()
위젯의 정렬
pack() 함수의 옵션 중에서 가로/세로로 정렬하는 방법으로 side=LEFT / RIGHT / TOP / BOTTOM방식이 있다. LEFT는 왼쪽부터, RIGHT는 오른쪽 부터, TOP은 위 BOTTOM은 아래부터 정렬된다.
from tkinter import *
from tkinter import messagebox
root = Tk()
root.title("혼공 GUI 연습")
root.geometry("200x200")
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()
위젯 사이에 여백 추가
위젯 사이에 여백을 주려면pack() 함수의 옵션 중 padx=픽셀값 / pady=픽셀값 방식을 사용한다.
from tkinter import *
root = Tk()
root.title("혼공 GUI 연습")
root.geometry("200x200")
button1 = Button(root, text="혼공1")
button2 = Button(root, text="혼공2")
button3 = Button(root, text="혼공3")
button1.pack(side=TOP, fill=X, padx=10, pady=10)
button2.pack(side=TOP, fill=X, padx=10, pady=10)
button3.pack(side=TOP, fill=X, padx=10, pady=10)
root.mainloop()
프레임, 엔트리, 리스트 박스
프레임은 화면을 여러 구역으로 나눌 때 사용한다. 엔트리는 입력 상자를 표현하고 리스트 박스는 목록을 표현한다.
from tkinter import *
root = Tk()
root.geometry("200x250")
######### 1 #########
upFrame = Frame(root)
upFrame.pack()
downFrame = Frame(root)
downFrame.pack()
######### 1 #########
######### 2 #########
editBox = Entry(upFrame, width = 10)
editBox.pack(padx = 20, pady = 20)
######### 2 #########
######### 3 #########
listbox = Listbox(downFrame, bg="yellow")
listbox.pack()
######### 3 #########
######### 4 #########
listbox.insert(END, "하나")
listbox.insert(END, "둘")
listbox.insert(END, "셋")
root.mainloop()
- upFrame / downFrame이라는 2개의 프레임을 생성하고 화면에 출력, 단 프레임은 구역을 나눴을 뿐 화면에 나타나지는 않음
- 입력을 위한 엔트리, root가 아닌 upFrame에 나타나도록 설정
- 리스트 박스, downFrame에 나타나도록 설정
- 리스트 박스에 데이터를 3건 입력, 옵션 중 END는 데이터를 제일 뒤에 첨부하라는 의미
3-2. 완전한 형태의 GUI 응용 프로그래밍
- GUI 화면에서 데이터의 입력과 수정이 가능하도록 하자.
- 초기화 버튼을 클릭하면 테이블이 삭제되고 다시 생성되도록 하자
import pymysql
from tkinter import *
from tkinter import messagebox
#메인 코드 함수 부
def insertData():
conn, cur = None, None
uid, uname, uemail, ubirth = "", "", "", ""
insertSql = ""
conn = pymysql.connect(host='127.0.0.1', port=3307, user='root', password='0000', db='soloDB', charset='utf8')
cur = conn.cursor()
## userTable에 입력될 값을 GUI환경에서 입력받은 값으로 넣어줌
uid = edtUid.get()
uname = edtUname.get()
uemail = edtUemail.get()
ubirth = edtUbirth.get()
insertSql = "INSERT INTO userTable VALUES ('" + uid + "', '" + uname + "', '" + uemail + "', " + ubirth + ")"
cur.execute(insertSql)
conn.commit()
conn.close()
messagebox.showinfo('성공', '데이터 입력 성공')
def selectData() :
#SELECT 결과를 리스트 박스에 출력하기 위한 리스트
strUid, strUname, strUemail, strUbirth = [], [], [], []
conn = pymysql.connect(host='127.0.0.1', port=3307, user='root', password='0000', db='soloDB', charset='utf8')
cur = conn.cursor()
cur.execute("SELECT * FROM userTable")
#제목 및 구분하기 위한 줄을 리스트에 추가
strUid.append("사용자 ID")
strUname.append("사용자 이름")
strUemail.append("사용자 이메일")
strUbirth.append("사용자 출생연도")
strUid.append("----------")
strUname.append("----------")
strUemail.append("----------")
strUbirth.append("----------")
while (True) :
row = cur.fetchone()
if row == None :
break;
strUid.append(row[0])
strUname.append(row[1])
strUemail.append(row[2])
strUbirth.append(row[3])
#화면의 출력되는 리스트 박스를 모두 비움
listUid.delete(0, listUid.size() - 1)
listUname.delete(0, listUname.size() - 1)
listUemail.delete(0, listUemail.size() - 1)
listUbirth.delete(0, listUbirth.size() - 1)
#각 리스트 박스에 앞에서 준비한 데이터를 채움
for tUid, tUname, tUemail, tUbirth in zip(strUid, strUname, strUemail, strUbirth) :
listUid.insert(END, tUid)
listUname.insert(END, tUname)
listUemail.insert(END, tUemail)
listUbirth.insert(END, tUbirth)
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)
edtUid = Entry(edtFrame, width=10)
edtUid.pack(side=LEFT, padx=10, pady=10)
edtUname = Entry(edtFrame, width=10)
edtUname.pack(side=LEFT, padx=10, pady=10)
edtUemail = Entry(edtFrame, width=10)
edtUemail.pack(side=LEFT, padx=10, pady=10)
edtUbirth = Entry(edtFrame, width=10)
edtUbirth.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)
listUid = Listbox(listFrame, bg= 'yellow')
listUid.pack(side=LEFT, fill=BOTH, expand=1)
listUname = Listbox(listFrame, bg= 'yellow')
listUname.pack(side=LEFT, fill=BOTH, expand=1)
listUemail = Listbox(listFrame, bg= 'yellow')
listUemail.pack(side=LEFT, fill=BOTH, expand=1)
listUbirth = Listbox(listFrame, bg= 'yellow')
listUbirth.pack(side=LEFT, fill=BOTH, expand=1)
root.mainloop()