※ Treeview에 대한 기본 사항 : 파이썬 Tkinter TreeView에 대한 기본
GUI 애플리케이션을 Python으로 개발할 때
데이터를 표 형식으로 보여줘야 하는 경우가 많습니다.
이런 상황에서 Python의 Tkinter 라이브러리의 Treeview 위젯은
매우 유용하게 사용될 수 있습니다.
그리고 표 형식의 데이터를 표시할 때 정렬은 매우 중요한 기능입니다.
이번 블로그 포스트에서는 Treeview의 헤더(제목)를 클릭할 때
해당 열을 기준으로 오름차순 또는 내림차순 정렬을 하는 방법을 알아보겠습니다.
전체코드
import tkinter as tk
from tkinter import ttk
data = [
{"Name": "홍길동", "Age": 30},
{"Name": "임꺽정", "Age": 25},
{"Name": "김개똥", "Age": 35},
{"Name": "이무기", "Age": 105},
]
sort_ascending = {"Name": True, "Age": True}
def refresh_treeview():
for row in tree.get_children():
tree.delete(row)
for item in data:
tree.insert("", "end", values=(item["Name"], item["Age"]))
def sort_treeview(column):
global data
ascending = sort_ascending[column]
data.sort(key=lambda x: x[column], reverse=not ascending)
sort_ascending[column] = not ascending
refresh_treeview()
root = tk.Tk()
tree = ttk.Treeview(root, columns=("Name", "Age"), show="headings")
tree.heading("Name", text="Name", command=lambda: sort_treeview("Name"))
tree.heading("Age", text="Age", command=lambda: sort_treeview("Age"))
tree.column("Name", width=150)
tree.column("Age", width=100)
tree.pack(fill=tk.BOTH, expand=True)
refresh_treeview()
root.mainloop()
이 코드를 실행하면 결과는 다음과 같습니다.
한번 누르면 오름차순, 한번 더 누르면 내림차순으로 정렬이 됩니다.
코드 설명
먼저저 간단한 Treeview를 만들어 줍니다.
root = tk.Tk()
tree = ttk.Treeview(root, columns=("Name", "Age"), show="headings")
tree.heading("Name", text="Name")
tree.heading("Age", text="Age")
tree.column("Name", width=150)
tree.column("Age", width=100)
tree.pack(fill=tk.BOTH, expand=True)
이제 아래 그림과 같은 간단한 Treeview의 뼈대가 만들어졌습니다.
이제 데이터를 추가해 보겠습니다.
리스트와 딕셔너리를 사용하여 이름과 나이에 관한 데이터를 만들었습니다.
data = [
{"Name": "Alice", "Age": 30},
{"Name": "Bob", "Age": 25},
{"Name": "Charlie", "Age": 35},
]
※ 파이썬 리스트 : 파이썬 리스트(Python List)
※ 파이썬 딕셔너리 : 파이썬(Python) Dictionary 만들고 수정, 접근하기
그다음 데이터를 Treeview 테이블에 넣습니다.
refresh_treeview() 함수를 만들고 호출합니다.
def refresh_treeview():
for item in data:
tree.insert("", "end", values=(item["Name"], item["Age"]))
root = tk.Tk()
tree = ttk.Treeview(root, columns=("Name", "Age"), show="headings")
tree.heading("Name", text="Name")
tree.heading("Age", text="Age")
tree.column("Name", width=150)
tree.column("Age", width=100)
tree.pack(fill=tk.BOTH, expand=True)
refresh_treeview()
우선 여기까지의 소스코드는 다음과 같습니다.
import tkinter as tk
from tkinter import ttk
data = [
{"Name": "홍길동", "Age": 30},
{"Name": "임꺽정", "Age": 25},
{"Name": "김개똥", "Age": 35},
{"Name": "이무기", "Age": 105},
]
def refresh_treeview():
for item in data:
tree.insert("", "end", values=(item["Name"], item["Age"]))
root = tk.Tk()
tree = ttk.Treeview(root, columns=("Name", "Age"), show="headings")
tree.heading("Name", text="Name")
tree.heading("Age", text="Age")
tree.column("Name", width=150)
tree.column("Age", width=100)
tree.pack(fill=tk.BOTH, expand=True)
refresh_treeview()
root.mainloop()
이 코드를 실행하면 아래 그림과 같이 데이터가 추가됩니다.
이제 헤더(제목)를 클릭했을 때 정렬되도록 함수를 만들어 보겠습니다.
sort_ascending = {"Name": True, "Age": True}
def sort_treeview(column):
global data
ascending = sort_ascending[column]
data.sort(key=lambda x: x[column], reverse=not ascending)
sort_ascending[column] = not ascending
refresh_treeview()
리스트의 정렬에 사용하기 위해
sort_ascending 변수를 설정하고,
기본적으로 이름과 나이 모두 TRUE로 설정하여 기본값을 내림차순으로 만듭니다.
엄밀히 말하면 여기서 내림차순을 정하는 것이 아니라
나중에 sort() 함수를 호출할 때 사용할 변수값을 지정하는 것 뿐입니다.
그다음 sort_ascending[column]을 통해 Name 또는 Age를 받고
해당 자료가 TRUE(내림차순) 인지 FALSE(오름차순) 인지를
변수 ascending에 전달합니다.
그리고 sort() 함수를 통해 해당 열을 정렬하는데
정렬방법(reverse)은 맨 처음 TRUE 즉, 내림차순으로 설정이 되어 있었으므로
not ascending을 통해 그 반대인 FALSE(오름차순)으로 정렬하도록 합니다.
저는 헤더(제목)를 처음 눌렀을 때는 오름차순
그다음은 내림차순으로 정렬되게 하고 싶었기 때문에 이렇게 설정을 했습니다.
그리고 현재 정렬 상태의 반대
즉, Name 열을 정렬했다면 Name의 정렬상태는 False로 바뀌었을 것이므로
바뀐 값을 sort_ascending에 반영해 줍니다.
결과적으로 sort_ascending는 {"Name": False, "Age": True}가 될 것입니다.
그 다음 refresh_treeview() 함수를 호출해 변경된 데이터를 반영해 줍니다.
이제 헤더(제목)를 클릭하면 함수를 호출하게 만들어줍니다.
tree.heading("Name", text="Name", command=lambda: sort_treeview("Name"))
tree.heading("Age", text="Age", command=lambda: sort_treeview("Age"))
※ lambda 함수 기초 : 파이썬(python) lambda 함수
여기까지 작성된 소스코드는 다음과 같습니다.
import tkinter as tk
from tkinter import ttk
data = [
{"Name": "홍길동", "Age": 30},
{"Name": "임꺽정", "Age": 25},
{"Name": "김개똥", "Age": 35},
{"Name": "이무기", "Age": 105},
]
sort_ascending = {"Name": True, "Age": True}
def refresh_treeview():
for item in data:
tree.insert("", "end", values=(item["Name"], item["Age"]))
def sort_treeview(column):
global data
ascending = sort_ascending[column]
data.sort(key=lambda x: x[column], reverse=not ascending)
sort_ascending[column] = not ascending
refresh_treeview()
root = tk.Tk()
tree = ttk.Treeview(root, columns=("Name", "Age"), show="headings")
tree.heading("Name", text="Name", command=lambda: sort_treeview("Name"))
tree.heading("Age", text="Age", command=lambda: sort_treeview("Age"))
tree.column("Name", width=150)
tree.column("Age", width=100)
tree.pack(fill=tk.BOTH, expand=True)
refresh_treeview()
root.mainloop()
여기까지 작성하고 실행하면 아래와 같이 결과가 나타납니다.
먼저 처음 실행화면입니다.
Name을 한번 눌렀을 때입니다.
그다음 Age를 눌렀을 때입니다.
이렇게 결과가 나오는 이유는 기존의 Treeview의 데이터를 지우지 않았기 때문입니다.
refresh_treeview() 함수에
기존 데이터를 지우는 코드를 추가합니다.
def refresh_treeview():
for row in tree.get_children(): # 추가 코드
tree.delete(row) # 추가 코드
for item in data:
tree.insert("", "end", values=(item["Name"], item["Age"]))
get_children() 함수는 Treeview에 있는 모든 항목의 ID를 리스트로 반환합니다.
insert() 함수를 통해 데이터를 입력할 때 해당 항목에 ID를 부여할 수 있는데
부여하지 않으면, 자동으로 부여를 해줍니다.
여기서는 부여하지 않았으므로, 자동으로 부여된 ID를 리스트로 반환한 후
해당 열을 모두 지워줍니다.
맨 처음 호출할 때에는 아무 데이터도 없으므로 상관이 없습니다.
마치며
전체 로직은 다음과 같습니다.
헤더를 누르면 sort_treeview() 함수를 호출하여 데이터를 정렬합니다.
그다음 refresh_treeview() 함수를 호출하여
Treeview에 있던 데이터를 모두 삭제하고
정렬된 데이터를 Treeview에 반영을 합니다.
여기를 방문하시면 더 많은 파이썬 관련 자료를 확인할 수 있습니다.
'파이썬(Python)' 카테고리의 다른 글
[ 파이썬 한글 자동화 ] 한글 문서(Hwp) 안의 표 개수 확인하기 (0) | 2024.10.11 |
---|---|
[ 파이썬 한글 자동화 ] 실행 중인 한글(Hwp, Hwpx) 프로그램 조작하기 (2) | 2024.10.10 |
[ Tkinter ] 파이썬(Python) Tkinter 달력에서 날짜 선택하기 : 달력 표시하기 Tkcalendar (0) | 2024.10.07 |
[ Basic ] 파이썬(Python) or 연산자로 값 할당하기 : If문 대신 or 연산자 사용하기 (0) | 2024.10.06 |
[ Tkinter ] 파이썬 Tkinter TreeView에 대한 기본 (0) | 2024.10.06 |