PyQt개발강좌, QTreeView로 트리 구조 구성

이 강좌에서는 PyQt를 사용하여 QTreeView를 통해 트리 구조를 어떻게 구성하고 사용하는지에 대해 다룰 것입니다. QTreeView는 트리 형태의 데이터를 시각적으로 표현하고 조작하는 데 유용한 위젯입니다. 이 강좌를 통해 우리는 트리 구조를 생성하고, 이를 QTreeView로 표시하는 방법을 배울 것입니다.

1. QTreeView의 기본 이해

QTreeView는 Qt 프레임워크에서 제공하는 위젯 중 하나로, 계층적인 데이터를 표시하는 데 사용됩니다. 이 위젯은 노드(node)와 자식 노드(child node)로 구성된 트리 구조를 통해 데이터를 관리하고, 사용자가 원하는 방식으로 데이터를 탐색할 수 있게 해 줍니다. 예를 들어, 파일 탐색기에서 폴더와 파일을 트리 구조로 표현하는 것을 생각해 볼 수 있습니다.

2. 기본적인 PyQt 애플리케이션 설정

PyQt 애플리케이션을 시작하려면 PyQt5 패키지를 설치해야 합니다. 시스템에 PyQt5가 설치되어 있지 않다면, 아래의 pip 명령어를 사용하여 설치할 수 있습니다.

pip install PyQt5

PyQt5를 설치한 후, 기본적인 애플리케이션을 설정하는 코드를 작성해 보겠습니다.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTreeView 예제")
        self.setGeometry(100, 100, 600, 400)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

3. QTreeView와 모델 설정

QTreeView를 사용하기 위해서는 모델이 필요합니다. QTreeView는 기본적으로 MVC(모델-뷰-컨트롤러) 패턴을 따릅니다. 적절한 데이터 구조를 설정한 후 이를 QTreeView에 연결해야 합니다.

QTreeView에 사용할 기본 모델로는 QStandardItemModel을 사용할 수 있습니다. 이 모델은 표준적인 데이터 구조를 가지며, 쉽게 데이터를 추가하고 수정할 수 있게 해 줍니다.

from PyQt5.QtWidgets import QTreeView, QVBoxLayout, QWidget, QStandardItemModel, QStandardItem

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTreeView 예제")
        self.setGeometry(100, 100, 600, 400)
        
        # QTreeView 및 모델 설정
        self.tree_view = QTreeView()
        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(["이름", "설명"])

        # 트리 노드 추가
        self.add_items(self.model)

        self.tree_view.setModel(self.model)
        self.setCentralWidget(self.tree_view)

    def add_items(self, model):
        # 루트 아이템 추가
        root_item = model.invisibleRootItem()

        # 첫번째 레벨
        item1 = QStandardItem("아이템 1")
        item2 = QStandardItem("아이템 2")
        
        # 두 번째 레벨
        sub_item1 = QStandardItem("서브 아이템 1.1")
        sub_item2 = QStandardItem("서브 아이템 2.1")
        
        # 아이템 추가
        root_item.appendRow(item1)
        root_item.appendRow(item2)
        item1.appendRow(sub_item1)
        item2.appendRow(sub_item2)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

4. QTreeView에 아이템 추가하기

위의 예제에서는 기본 트리 구조를 정의했지만, 더 복잡한 데이터 모델을 다루고 싶을 수 있습니다. QStandardItemModel을 확장하여 다양한 유형의 아이템을 추가해 보겠습니다.

def add_items(self, model):
    root_item = model.invisibleRootItem()

    # 여러 아이템 추가
    categories = [
        ("프로그래밍", ["Python", "C++", "Java"]),
        ("데이터베이스", ["MySQL", "PostgreSQL", "SQLite"]),
        ("웹 개발", ["HTML", "CSS", "JavaScript"])
    ]

    for category, items in categories:
        category_item = QStandardItem(category)
        root_item.appendRow(category_item)
        for item in items:
            sub_item = QStandardItem(item)
            category_item.appendRow(sub_item)

5. 사용자 인터페이스(UI) 확장하기

QTreeView의 기본적인 기능을 확장하면 사용자가 원하는 다양한 인터페이스를 제공할 수 있습니다. 아래의 예제에서는 QTreeView의 아이템 클릭 이벤트를 처리하여, 사용자가 선택한 아이템의 이름을 표시하는 방법을 소개합니다.

from PyQt5.QtCore import QModelIndex
from PyQt5.QtWidgets import QMessageBox

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTreeView 예제")
        self.setGeometry(100, 100, 600, 400)

        self.tree_view = QTreeView()
        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(["이름", "설명"])
        self.add_items(self.model)

        self.tree_view.setModel(self.model)
        self.tree_view.clicked.connect(self.on_item_clicked)  # Click Event
        self.setCentralWidget(self.tree_view)

    def on_item_clicked(self, index: QModelIndex):
        item = self.model.itemFromIndex(index)  # 클릭한 아이템 가져오기
        item_name = item.text()  # 아이템의 텍스트 가져오기
        QMessageBox.information(self, "아이템 클릭", f"클릭한 아이템: {item_name}")

6. QTreeView와 Drag & Drop 기능

QTreeView는 드래그 앤 드롭 기능을 쉽게 구현할 수 있습니다. 사용자가 트리 구조를 직관적으로 수정할 수 있게 해 주기 때문에 매우 유용합니다. 이를 위해 모델의 드래그 앤 드롭 속성을 설정하고, 관련 기능을 활성화해야 합니다.

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTreeView 예제")
        self.setGeometry(100, 100, 600, 400)

        self.tree_view = QTreeView()
        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(["이름", "설명"])
        self.add_items(self.model)

        self.tree_view.setModel(self.model)
        self.tree_view.setDragEnabled(True)  # 드래그 가능 설정
        self.tree_view.setDropIndicatorShown(True)  # 드롭 인디케이터 표시
        self.tree_view.setAcceptDrops(True)  # 드롭 허용
        self.tree_view.dropEvent = self.drop_event  # 드롭 이벤트 연결

        self.setCentralWidget(self.tree_view)

    # 드롭 이벤트 처리
    def drop_event(self, event):
        self.model.itemFromIndex(self.tree_view.selectedIndexes()[0]).setText("변경된 아이템")
        event.accept()

7. QTreeView의 스타일링

QTreeView의 외관은 사용자에게 중요한 사용자 경험을 제공합니다. Qt의 스타일 시트를 사용하여 QTreeView의 색상, 글꼴, 아이콘 등을 변경할 수 있습니다. 스타일 시트는 CSS(Cascading Style Sheets)와 비슷한 방식으로 작성됩니다.

self.tree_view.setStyleSheet("""
    QTreeView {
        background-color: #f0f0f0;
        color: #333;
    }
    QTreeView::item {
        padding: 10px;
    }
    QTreeView::item:selected {
        background-color: #007BFF;
        color: white;
    }
""")

8. 네비게이션 단축키 구현하기

PyQt에서는 키 이벤트를 통해 사용자 인터페이스의 인터랙션을 강화할 수 있습니다. QTreeView의 항목 사이를 빠르게 탐색할 수 있는 단축키를 설정해 보겠습니다.

from PyQt5.QtGui import QKeySequence

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTreeView 예제")
        self.setGeometry(100, 100, 600, 400)

        self.tree_view = QTreeView()
        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(["이름", "설명"])
        self.add_items(self.model)
        self.tree_view.setModel(self.model)

        # 단축키 설정
        open_action = self.tree_view.addAction("열기")
        open_action.setShortcut(QKeySequence("Ctrl+O"))  # Ctrl+O 키 설정
        open_action.triggered.connect(self.on_open_action)

        self.setCentralWidget(self.tree_view)

    def on_open_action(self):
        selected_item = self.tree_view.currentIndex()
        if selected_item.isValid():
            item_text = self.model.itemFromIndex(selected_item).text()
            QMessageBox.information(self, "아이템 열기", f"{item_text}을(를) 열었습니다.")

9. 응용 프로그램 종료 및 정리

애플리케이션 종료 시 불필요한 자원을 정리하는 것도 중요한 작업입니다. PyQt에서는 QApplication의 종료 메소드를 통해 클린업 작업을 실행할 수 있습니다. 아래는 애플리케이션을 종료할 때 로그를 생성하는 간단한 예제입니다.

class MainWindow(QMainWindow):
    def closeEvent(self, event):
        print("애플리케이션을 종료합니다...")
        event.accept()  # 종료 이벤트 허용

10. 프로젝트 패키징 및 배포

이제 QTreeView를 사용하는 애플리케이션의 기초를 익혔으므로, 이 애플리케이션을 패키징하고 배포하는 방법에 대해 다루겠습니다. PyInstaller를 사용하여 PyQt 애플리케이션을 독립 실행형 실행 파일로 변환할 수 있습니다.

pip install pyinstaller
pyinstaller --onefile your_script.py

위의 명령어로 실행 가능한 파일을 생성할 수 있습니다. 생성된 파일은 ‘dist’ 폴더에 위치합니다.

결론

이번 강좌에서는 PyQt에서 QTreeView를 사용하는 방법과 이를 통해 다양한 형태의 데이터를 보여주는 방법을 살펴보았습니다. QTreeView는 사용자가 데이터를 직관적으로 관리할 수 있도록 도와주며, 여러 가지 기능을 통해 사용자의 경험을 개선할 수 있습니다. 여기서 학습한 내용들을 바탕으로 자신만의 애플리케이션을 만들어 보세요.

내부 통신 및 UI/UX 관련 추가 기능들도 구현해보시기 바랍니다. QTreeView를 활용한 프로젝트는 다양한 분야에 적용할 수 있으며, 특히 데이터 중심의 애플리케이션에서 큰 효과를 볼 수 있습니다.

궁금한 점이나 피드백은 언제든지 남겨주세요. 다음 강좌에서 만나요!