본문 바로가기
Programming/Python

Tkinter GUI와 함께 하는 파일 처리 연습 - 001

by The Programmer 2025. 5. 27.

1. Introduction

 
( 중/고급 : 제가 쓰려고 참고용으로 올려둡니다. )
 
Tkinter GUI와 함께 하는 파일 처리 연습용 예제입니다. 특정 폴더명이 위치로 주어지면 이렇게 지정된 위치에 포함되어 있는 파일 목록을 구하는 함수를 만들고 이 함수를 사용해서 TreeView에 파일 목록을 표시합니다. 기능은 이게 전부입니다. 이 예제는 다음 핵심 두 항목들에 대한 구현을 포함합니다.
 
1) 파일 목록을 알아내는 방법.
2) TreeView 에 표시하는 방법.
 
같은 결과를 가져오는 서로 다른 방법이 존재하지만, 여기서는 비교적 좀 더 쉽고 간결 명확한 방법을 선택합니다. 코드의 간결성을 위해서 파일이나 폴더 선택을 위한 대화상자를 사용하지 않았습니다. (혹 tkinter 관련 중급 이상 다른 예제들에 포함되어 있으니 찾아보세요. SR 예제인가요? 아마도. ^.^; )
 
TreeView 사용법은 다른 위젯에 비해 상대적으로 제법 복잡한 편이기 때문에 한 번에 하나의 기능을 익혀가는 정도의 작은 예제들로 학습해 나가는 것이 좋겠습니다.
 
 

2. Code

 
import tkinter as tk
from tkinter import ttk
import os

def load_files():
    folder_path = folder_entry.get()
    if os.path.isdir(folder_path):
        
file_list.delete(*file_list.get_children())
        
# 기존 항목 삭제
         for file in os.listdir(folder_path):
            file_list.insert("", "end", values=[file])

# GUI 설정
root = tk.Tk()
root.title("파일 목록 보기")

frame = ttk.Frame(root, padding=10)
frame.grid(row=0, column=0, sticky="wnes")

folder_entry = ttk.Entry(frame, width=50)
folder_entry.grid(row=0, column=0, padx=5, pady=5)

load_button = ttk.Button(frame, text="불러오기", command=load_files)
load_button.grid(row=0, column=1, padx=5, pady=5)

file_list = ttk.Treeview(frame, columns=("파일명",), show="headings")
file_list.heading("파일명", text="파일명")
file_list.grid(row=1, column=0, columnspan=2, padx=5, pady=5)

root.mainloop()


 

3. Result

 
너무 간단한 결과라 패스... ^.^;
 
 

4. Notes

 
■ 'ttk.Treeview'는 계층적인 데이터를 표시하는 강력한 'Tkinter' 위젯입니다. 이하에서는 그 주요 기능들을 정리해 봅니다. 기능 전부가 포함된 것은 아닙니다 :

1) 컬럼 및 헤더 설정
- 'columns' 옵션을 사용하여 여러 개의 열을 정의할 수 있습니다.
- 'heading()' 메서드를 이용해 각 열의 헤더를 설정할 수 있습니다.
예:

treeview.heading("파일명", text="파일명")

2) 항목(Item) 추가 및 삭제
- 'insert()' 메서드를 사용해 데이터를 추가할 수 있습니다.
- 'delete()' 메서드를 사용해 특정 항목을 삭제할 수 있습니다.
예:
treeview.insert("", "end", values=["example.txt"])
treeview.delete(*treeview.get_children())
# 모든 항목 삭제

3) 부모-자식 관계 설정 (계층 구조)
- 'iid'를 사용해 계층적인 구조를 만들 수 있습니다.
예:
treeview.insert("", "end", iid="parent", values=["폴더"])
treeview.insert("parent", "end", values=["파일1.txt"])

4) 선택 및 이벤트 처리
- 사용자가 선택한 항목을 가져올 수 있습니다.
- 'bind()' 메서드를 사용해 특정 이벤트 발생 시 콜백 함수를 실행할 수 있습니다.
예:
selected_items = treeview.selection()
treeview.bind("<<TreeviewSelect>>", lambda e: print(treeview.selection()))

5) 컬럼 너비 및 정렬 조정
- 'column()' 메서드를 사용해 컬럼의 너비, 정렬 등을 조정할 수 있습니다.
예:
treeview.column("파일명", anchor="center", width=200)

 
이 외에도 스크롤바를 추가하거나 스타일을 변경하는 기능도 활용할 수 있습니다.
(이 부분은 시간 나면, 추후 업데이트에서. ^.^;)
 
 
핵심 파일 처리 함수
 
def load_files():
    folder_path = folder_entry.get()
    if os.path.isdir(folder_path):
        file_list.delete(*file_list.get_children())
         
# 기존 항목 삭제
         for file in os.listdir(folder_path):
            file_list.insert("", "end", values=[file])

 
 
folder_path = folder_entry.get()
폴더명 입력을 위한 엔트리 위젯 하나. 여기서 get() 함수(=메소드 혹은 메서드method)는 엔트리에 입력된 텍스트를 뜻합니다. get() 함수가 엔트리에 입력된 내용을 조사해서 그 내용을 '가져옵니다(get)'. 보통은 파일/폴더 선택용 대화상자를 사용하나 여기서는 코드량을 늘리지 않기 위해서 폴더명을 직접 타이핑 쳐서 선택합니다.
 
if os.path.isdir(folder_path):
os.path.isdir()함수는 제공된 폴더명이 실제로 존재하는지 확인하는 역할을 합니다. 폴더가 존재하고 (파일이 아니라) 폴더이면 true가 되어 if 조건문 코드들을 실행합니다.
 
file_list.delete(*file_list.get_children())
# 기존 항목 삭제

 
file_list.delete()에서 file_list는 다음처럼 생성된 트리뷰 객체입니다.
file_list = ttk.Treeview(frame, columns=("파일명",), show="headings")
 
file_list.delete(*file_list.get_children())
# 기존 항목 삭제

트리뷰 위젯에 이제 표시될 내용을 위해서 이전에 있던 항목 정보들을 미리 사전에 싹 다 지우고 트리뷰 목록을 청소해서 전부 텅 비웁니다. 기존 항목이 하나도 없는 상태면 그대로, 기존 항목들이 하나라도 존재한다면 전부 목록에서 지웁니다. 목록을 비운다는 뜻이지, 트리뷰에 나타난 해당 파일이나 폴더를 실제로 지우는 것은 절대 아닙니다.
 
*file_list.get_children()
get_children() 함수는 전체 목록의 하위 개념으로서의 개별 항목들을 '전부' 찾아오는(=구해오는) 역할을 합니다.
 
 
언패킹(unpacking) 연산자

위에서 '*' (별표, asterisk)는 언패킹(unpacking) 연산자로 사용됩니다.

■ 언패킹의 역할
'file_list.get_children()'은 'Treeview'의 모든 항목(자식 요소)의 ID 리스트를 반환합니다. 예를 들어, 다음처럼 여러 개의 항목이 있을 수 있습니다.
예:
ids = file_list.get_children()    # 예: ('I001', 'I002', 'I003')

하지만 'file_list.delete()' 메서드는 개별 ID를 인수로 받도록 설계되어 있습니다. 즉, 리스트 자체를 인수로 전달하면 오류가 발생할 수 있습니다.
예: 
file_list.delete(ids)    # 오류 발생 가능

이때, 대신 별표('*')를 사용하면 리스트의 각 요소가 개별 인수로 전달됩니다.
예:
file_list.delete(*ids)    # 각 ID가 개별 인수로 전달됨

즉, '*file_list.get_children()'는 '"I001", "I002", "I003"' 처럼 각각의 ID를 'delete()' 메서드에 개별 인수로 넘겨주어 모든 항목을 올바르게 삭제할 수 있도록 해줍니다.
 
 
단일 요소 튜플
 
■  file_list = ttk.Treeview(frame, columns=("파일명",), show="headings")
columns=("파일명",) 부분에서처럼 "파일명" 다음에 콤마(,)가 있는 이유는 단일 요소 튜플을 정의하기 위해서 입니다.

■ 단일 요소 튜플 추가 설명
- columns=("파일명",) 부분에서 "파일명"은 Treeview의 열(column) 이름을 설정하는 역할을 합니다.
- 일반적으로 튜플을 만들 때 여러 요소가 있을 경우 (a, b, c)처럼 정의하면 됩니다.
- 하지만 튜플이 단 하나의 요소만 가질 때는 ("파일명",)처럼 콤마를 포함해야 합니다. 그렇지 않으면 ("파일명")을 str(문자열)로 인식해버립니다. 의미상 오류가 됩니다.

■ 예제 비교

- 올바른 단일 요소 튜플
columns = ("파일명",)    # 타입: tuple

 
- 잘못된 정의 (문자열이 됨)
columns = ("파일명")    # 타입: str

 
즉, ("파일명",)처럼 콤마를 포함하지 않으면 "파일명"을 튜플이 아닌 문자열로 인식하기 때문에 Treeview에서 올바르게 작동하지 않을 수 있습니다.
 
 
■ 응용 연습 과제
1) 트리뷰에 스크롤바 추가하기.
2) 트리뷰에 스타일 적용하기.
 
 

5. Files

 
Not yet! ^.^;
짧은 코드라.
 
 

6. Ref.

 
1) 강환수, 신용현, [  파이썬으로 배우는 누구나 코딩 ] 홍릉.
2) 천인국, [ Python Express ] 생능.
3) 김영탁, [ 파이썬 프로그래밍 ] 홍릉.
4) 앨런 무어, [ Tkinter를 사용한 파이썬 GUI 프로그래밍 2/e ] 에이콘.
5) Mark Lutz, [ Programming Python, 4th. Ed. ] O'Reilly.
 
 
Happy Programming!
 
^.^;