본문 바로가기

카테고리 없음

8. SQL과 파이썬 연결-3

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    #########

  1. tkinter는 파이썬에서 GUI 관련 모듈을 제공해 주는 표준 윈도 라이브러리이다.
  2. Tk()는 기본이 되는 윈도를 반환하는데, 이를 root라는 변수에 넣었다. Tk()를 루트 윈도라고도 부르며 꼭 필요한 요소이다.
  3. 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()
  1. upFrame / downFrame이라는 2개의 프레임을 생성하고 화면에 출력, 단 프레임은 구역을 나눴을 뿐 화면에 나타나지는 않음
  2. 입력을 위한 엔트리, root가 아닌 upFrame에 나타나도록 설정
  3. 리스트 박스, downFrame에 나타나도록 설정
  4. 리스트 박스에 데이터를 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()