Project/[Python] 도서 정보 입력 프로그램

[도서 입력 프로그램] 7. Tkinter GUI 제작

CodeNook; 2024. 6. 14. 14:22

[도서 정보 자동 입력 프로그램] 7. Tkinter GUI 제작


드디어 길고긴 프로그램 세팅이 끝났고, 이제 이 프로그램을 사용하기 쉽게 작동할 GUI(Graphic User Interface)를 설정할 차례다.

 

사실 처음에는 GUI까지 세팅할것 없이 그냥 콘솔창에서 간략하게 키보드 입력을 통해 프로그램을 작동하도록 만들 계획이었으나, 프로그램을 만들면서 생각보다 코딩에 있어 ChatGPT의 도움이 아주 강력했고 계속해서 더 잘만들고 싶다는 욕심이 생겨서 공부겸, 사용편의성 개선겸 도전해보게 되었다.

 

GUI를 위해 사용할 파이썬 라이브러리는 Tkinter와 그와 비슷한 TTKBootstrap이다.

Tkinter는 파이썬 기본 GUI 라이브러리인데 직관적이라 익히기 쉬운 장점이 있지만, 아무래도 디자인이 좀 old하다는 단점이 있다. 

TTKBootstrap은 Tkinter에 웹 CSS로 유명한 Bootstrap 디자인을 적용한 라이브러리인데, 사용법이 Tkinter와 유사하여 익히기 쉬우면서도 디자인이 Tkinter보다 더 깔끔해서 사용해보았다. 그런데 결론적으로 얘기하자면, 그냥 Tkinter를 사용하는게 더 가볍고 간결하며, 정말 디자인을 생각한다면 PyQt같은 다른 라이브러리를 사용하는것을 추천한다. TTKBootstrap은 그 중간사이의 애매한 그 무언가이다.

 

아무튼,

Tkinter로 GUI를 디자인하는 것은 마치 테트리스 블록 쌓는것과 같다. Tkinter에는 Button, Entry, Label, Frame, Checkbutton 등 여러가지 디자인 요소인 위젯(widget)이 있는데 이것들을 하나하나 선언한다음 pack(쌓기)메서드를 통해 인터페이스에 나타나도록 선언해준다. (배치를 위한 메서드에는 pack이외에도 grid, place가 있지만 여기선 pack만 해당)

 

테트리스 블록쌓는 것과 비슷한 Tkinter 위젯 배치

예를들어,

버튼을 하나 만들고 배치하고 싶다면 먼저 버튼을 정의해준다음 그 정의된 버튼에 pack 메서드로 위치나 여백 등을 설정해주면 화면에 보이게 된다. pack이나 다른 배치 메서드가 없다면 위젯을 정의했어도 화면이 나타나지 않는다.

 

import tkinter as tk

button = tk.Button("배치할 위치(기본화면 또는 프레임), text="(버튼 텍스트)", command=(연결할 함수))
button.pack(side="위치(left, right 등)", fill="(x축 또는 y축으로 채우기)", expand=(확대해서 채울지 여부), padx='(x축 여백)', pady='(y축여백)')

 

 

만약 화면을 나눠서 위젯을 배치하고 싶다면 먼저 Frame이나 LabelFrame(제목이 있는 프레임)을 배치하고 그 안에 위젯을 넣어주면 가능하다. 그리하여 완성한 GUI는 아래와 같다.

 

 

왼쪽의 도서목록 LabelFrame에서 현재 업로드된 알라딘의 도서목록을 조회할수 있고 책을 클릭하면 오른쪽 선택된 도서정보 LabelFrame에 크롤링한 도서 정보를 보여준다. '이전 페이지', '다음 페이지'버튼으로 알라딘 도서목록을 넘기면서 확인가능하다.

선택된 도서정보가 맞는지 확인하고 만약 잘못된 부분이 있을 경우 Entry 위젯 내용을 수정하면 수정된 내용으로 Yes24에 입력이 가능하다.

마지막 판매가격은 알라딘과 다르게 설정할 수 있게 해놨고, 편의를 위해 1,000원 인상, 10%인상 버튼을 추가했다.

자체 상품 코드의 경우 알라딘에서 바로 크롤링할수 없어서, Tkinter의 filedialog 기능을 사용해서 업로드 버튼을 클릭하면 알라딘의 엑셀파일을 읽어서 선택된 도서 제목에 맞는 자체 상품코드를 조회해 출력하도록 설정해놨다.

(참고:[도서 입력 프로그램] 6. Pandas 데이터 처리)

[Yes24로 입력]버튼 클릭하기 전에 '웹에 최종 등록전 마지막으로 확인' CheckBox를 선택하면 Yes24로 최종 등록하기 전에 계속 진행할지 확인 메시지를 띄워준다.

 

GUI관련 모든 코드를 설명하기엔 지면이 부족해서 몇가지 중요사항만 짚어보자.

 

1. 알라딘에서 도서 이름 크롤링해서 보여주기

직접 알라딘 API등에 접근해서 DB를 가져오는건 못하고, 그때그때 웹페이지를 크롤링해서 도서목록을 Tkinter의 treeview 위젯으로 보여주는 것으로 코딩을 짜보았다. Treeview에서는 굳이 보이진 않지만 도서명을 크롤링할때 해당 도서 http링크까지 같이 크롤링해서 다음 단계 진행때 사용하도록 남겨두었다.

 

○ Treeview 설정

import tkinter as tk
from tkinter import ttk

#스타일 설정
ttks=ttk.Style(root)
ttks.configure("Treeview.Heading", background="black", foreground="white", font=("맑은 고딕 bold", 14))

#페이지 번호
page_num = tk.StringVar()
page_num.set("1")

#트리뷰 설정
tree = ttk.Treeview(frame_one, columns=("book_names"), show="headings", height=25)
tree.heading("book_names", text="도서명", anchor="center")
tree.column("book_names", width=420)
ttks.configure('Treeview', rowheight=24)
tree.pack(side="top", padx=5, pady=10)

#트리뷰 특정 이벤트 설정, 선택시 on_select함수 실행
tree.bind('<<TreeviewSelect>>', on_select)

 

 

알라딘에서 도서명 수집 후 트리뷰에 목록 보여주기

#알라딘 정보수집 함수
def aladincrawl(page_num, tree):
    url = "(알라딘주소)"+str(page_num) #주소 뒤 페이지번호는 f스트링 처리

	#도서 이름과 링크 크롤링
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    names = soup.select('(책 목록 CSS Selector 주소)')
    links = soup.select('(책 링크 CSS Selector 주소)')

    book_names = [i.text for i in names]
    book_links = [i.attrs['href'] for i in links]
    book_info = list(zip(book_names, book_links))

    # 기존 트리뷰 내용 삭제 (tree는 treeview 객체)
    for i in tree.get_children():
        tree.delete(i)

    # 새로운 도서 정보 삽입
    for i in book_info:
        tree.insert("", "end", values=i)

 

 

○ Treeview에서 책 선택시 선택된 도서 정보에 출력하는 함수설정

#선택시 정보 출력 함수
def on_select(event): 
    selected_item = tree.selection()[0]
    item_values = tree.item(selected_item, 'values')
    if item_values:
        url = item_values[1] #크롤링한 도서정보 링크 선택
        book_info = aladin_extract(url) #상세 정보 수집 함수(aladin_extract) 실행
        
        #수집한 상세정보를 선택된 도서정보 프레임에서 보여주기
        if book_info:
        	#기존 Entry나 Label에 있던 내용 삭제(delete)후 새 내용 삽입(insert)
            bookname_e.delete(0, tk.END)
            bookname_e.insert(0, str(book_info[0]))
            #...중략...
            
            #함수 외부에서도 사용하기 위해 변수 global선언
            global info
            info = book_info

 

위 함수에서 aladin_extract(url)부분은 그동안 BeautifulSoup 등을 통해 수집한 알라딘 도서 정보수집 코드를 함수에 넣은것이라 보면 된다. (참고: [도서 입력 프로그램] 2. BeautifulSoup 알라딘 도서 정보 수집)

 

 

2. 수정한 도서 정보 반영해서 Yes24 입력 실행하기

기존에 표시된 선택된 도서정보에서 수정이 발생할 경우 수정된 정보를 기준으로 Yes24에 입력하기 위해서는, get메서드를 통해 Entry 위젯에 입력된 정보를 다시 변수에 저장하고 그 변수를 기준으로 Yes24에 입력하면 된다.

 

 

3. 체크박스 선택 여부 반영해서 Yes24 입력 실행하기

체크박스 선택여부를 반영하기 위해서는 입력 실행 함수내에서 체크박스 값(선택시 1, 미선택시0)을 기준으로 if문을 작성하면 된다. 이때 체크박스를 처음 선언하는 과정에서 미리 Var값을 지정해줘야 한다. (처음에 이것을 몰라서 한참을 헤매다 ChatGPT의 도움으로 해결했다.)

#체크버튼 값이 저장될 변수 선언
check_var = tk.IntVar() 

#체크버튼 설정 (tb는 TTKBootstrap이다.)
check = tb.Checkbutton(frame_row6, bootstyle="primary-round-toggle", variable=check_var)

 

위에서 처럼 체크박스를 만들어준다음 Yes24입력 함수 내에서 최종 등록 버튼 클릭 전에 if문으로 check_var가 1이면 확인메시지를 띄우고, 0이면 그대로 진행하도록 코딩해주면 된다.

 

 

 

이외에도 함수연결 순서 등 여러가지 골치아픈 일들이 있었으나, 모든 내용을 다 적기엔 복잡해지므로 생략하도록하겠다.

 

이리하여 드디어 GUI까지 완성해서 프로그램 디자인이 완료되었다. 이제 대망의 마지막 배포작업이다. Pyinstaller를 활용해서 exe파일을 만들어 배포할 예정인데 이것도 의외의 시행착오가 있었다. 그 내용은 다음 포스팅에서 알아보도록 하자.

 

이번 포스팅은 여기까지 😎

이전글: [도서 입력 프로그램] 6. Pandas 데이터 처리

 

[도서 입력 프로그램] 6. Pandas 데이터 처리

[도서 정보 자동 입력 프로그램] 6. Pandas 데이터 처리 세상은 넓고 예외는 많다.이제 좀 다 끝내고 GUI로 넘어가나 싶었는데 한가지 아쉬운점이 남았다. 바로 란이다. 이 부분은 도서주문이 들어

codenook.site

 

다음글: [도서 입력 프로그램] 8. Pyinstaller exe 파일 배포

 

[도서 입력 프로그램] 8. Pyinstaller exe 파일 배포

[도서 정보 자동 입력 프로그램] 8. Pyinstaller exe 파일 배포  이제 모든 작업을 마무리하고 마지막으로 py파일을 exe파일로 만들어서 배포작업만 남았다.파이썬의 단점은 배포가 어렵다는 점이다.

codenook.site