PyQt개발강좌, Property Browser를 통한 속성 관리 UI 구현

안녕하세요. 이번 강좌에서는 PyQt를 사용하여 속성 관리 UI를 구현하는 방법에 대해 알아보겠습니다. 특히, Property Browser를 이용하여 다양한 속성을 관리하는 방법을 중점적으로 다룰 예정입니다. PyQt는 Python에서 GUI 애플리케이션을 개발할 수 있도록 도와주는 라이브러리로, 강력하면서도 직관적인 인터페이스 제공으로 인기를 끌고 있습니다.

1. Property Browser란?

Property Browser는 개발자가 객체의 속성을 쉽게 수정하고 관리할 수 있도록 돕는 UI 요소입니다. 일반적으로 3D 모델링 소프트웨어나 게임 엔진과 같은 복잡한 시스템에서 사용되며, 사용자가 실시간으로 객체의 속성을 편집할 때 매우 유용합니다. 이러한 기능은 특히 속성이 많은 객체를 효율적으로 관리해야 하는 애플리케이션 개발 시 중요한 역할을 합니다.

예를 들어, 사용할 수 있는 속성으로는 색상, 크기, 위치 등이 있으며, 이러한 속성을 변화시키면서 실시간으로 결과를 확인할 수 있습니다. PyQt를 통해 이러한 Property Browser를 어떻게 구현할 수 있는지 살펴보겠습니다.

2. PyQt 설치하기

Property Browser를 구현하기 위해 먼저 PyQt를 설치해야 합니다. PyQt는 pip를 통해 쉽게 설치할 수 있습니다. 아래의 명령어를 사용하여 PyQt5를 설치합니다:

pip install PyQt5

3. 기본 UI 설정하기

Property Browser를 구현하기 위해, 기본 UI를 설정합니다. PyQt의 QWidgetQVBoxLayout을 사용하여 기본 창을 생성하고, 속성 변경을 위한 위젯을 추가합니다.

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit
class PropertyBrowser(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Property Browser")
        self.setGeometry(100, 100, 300, 400)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.create_widgets()

    def create_widgets(self):
        self.layout.addWidget(QLabel("속성 이름:"))
        self.property_name_input = QLineEdit(self)
        self.layout.addWidget(self.property_name_input)

        self.layout.addWidget(QLabel("속성 값:"))
        self.property_value_input = QLineEdit(self)
        self.layout.addWidget(self.property_value_input)

        # 속성 저장 버튼 추가
        self.save_button = QPushButton("속성 저장", self)
        self.save_button.clicked.connect(self.save_property)
        self.layout.addWidget(self.save_button)
        
    def save_property(self):
        property_name = self.property_name_input.text()
        property_value = self.property_value_input.text()
        # 저장 로직 추가 필요한 경우

if __name__ == "__main__":
    app = QApplication([])
    window = PropertyBrowser()
    window.show()
    app.exec_()

4. 속성 관리 기능 추가하기

기본 UI가 생성되었으니, 속성을 동적으로 관리하고 수정하는 기능을 추가해보겠습니다. 이를 위해 각 속성을 Python 객체로 저장하고 리스트 형태로 관리할 것입니다.

class Property:
    def __init__(self, name, value):
        self.name = name
        self.value = value

class PropertyBrowser(QWidget):
    def __init__(self):
        super().__init__()
        # ... (이전 코드)

        self.properties = []  # 속성 리스트 초기화

    def save_property(self):
        property_name = self.property_name_input.text()
        property_value = self.property_value_input.text()
        
        # 속성 추가
        new_property = Property(property_name, property_value)
        self.properties.append(new_property)
        print(f"저장된 속성: {new_property.name} = {new_property.value}")

        # 입력 필드 초기화
        self.property_name_input.clear()
        self.property_value_input.clear()

5. 동적 속성 표시 구현하기

사용자가 속성을 입력할 때마다 동적으로 속성을 표시할 수 있는 기능을 추가해보겠습니다. 리스트 위젯을 사용하여 속성이 추가될 때마다 UI에 갱신됩니다.

from PyQt5.QtWidgets import QListWidget, QPushButton, QVBoxLayout, QHBoxLayout

class PropertyBrowser(QWidget):
    def __init__(self):
        super().__init__()
        # ... (이전 코드)
        
        self.property_list = QListWidget(self)
        self.layout.addWidget(self.property_list)

    def save_property(self):
        property_name = self.property_name_input.text()
        property_value = self.property_value_input.text()

        # 속성 추가
        new_property = Property(property_name, property_value)
        self.properties.append(new_property)

        # 리스트 위젯에 추가
        self.property_list.addItem(f"{new_property.name} = {new_property.value}")
        
        # 입력 필드 초기화
        self.property_name_input.clear()
        self.property_value_input.clear()

6. 속성 수정 기능 구현하기

속성을 수정할 수 있는 기능도 추가해야 합니다. 사용자가 리스트에서 속성을 선택하고 수정할 수 있게 하여 편리한 UI를 제공합니다.

class PropertyBrowser(QWidget):
    def __init__(self):
        super().__init__()
        # ... (이전 코드)

        self.edit_button = QPushButton("수정", self)
        self.edit_button.clicked.connect(self.edit_property)
        self.layout.addWidget(self.edit_button)

    def edit_property(self):
        selected_item = self.property_list.currentItem()
        if selected_item:
            index = self.property_list.row(selected_item)
            property_name = self.property_name_input.text()
            property_value = self.property_value_input.text()

            # 속성 수정
            self.properties[index].name = property_name
            self.properties[index].value = property_value
            
            # 리스트에 수정된 내용 업데이트
            self.property_list.item(index).setText(f"{property_name} = {property_value}")
            
            # 입력 필드 초기화
            self.property_name_input.clear()
            self.property_value_input.clear()

7. 속성 삭제 기능 구현하기

속성을 삭제할 수 있는 기능도 제공합니다. 사용자가 리스트에서 속성을 선택하고 삭제 버튼을 클릭하면 해당 속성이 삭제됩니다.

class PropertyBrowser(QWidget):
    def __init__(self):
        super().__init__()
        # ... (이전 코드)

        self.delete_button = QPushButton("삭제", self)
        self.delete_button.clicked.connect(self.delete_property)
        self.layout.addWidget(self.delete_button)

    def delete_property(self):
        selected_item = self.property_list.currentItem()
        if selected_item:
            index = self.property_list.row(selected_item)
            self.properties.pop(index)  # 리스트에서 삭제
            self.property_list.takeItem(index)  # UI에서 삭제

8. 성능 개선 및 최적화

프로퍼티 브라우저의 성능을 개선하기 위해 추가적인 최적화를 수행할 수 있습니다. 예를 들어, 속성을 저장할 때마다 상태를 파일로 저장하거나, 초기화할 수 있는 로직을 추가하여 사용자가 편리하게 사용할 수 있도록 합니다.

import json

class PropertyBrowser(QWidget):
    # ... (이전 코드)

    def save_properties_to_file(self):
        with open("properties.json", "w") as f:
            json.dump([{'name': p.name, 'value': p.value} for p in self.properties], f)

    def load_properties_from_file(self):
        try:
            with open("properties.json", "r") as f:
                properties = json.load(f)
                for prop in properties:
                    self.properties.append(Property(prop['name'], prop['value']))
                    self.property_list.addItem(f"{prop['name']} = {prop['value']}")
        except FileNotFoundError:
            print("파일을 찾을 수 없습니다.")

9. 코드의 최종 형태

지금까지 논의한 모든 요소가 포함된 최종 코드는 다음과 같습니다. 이 코드를 통해 간단한 Property Browser를 구현할 수 있습니다.

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QListWidget, QPushButton
import json

class Property:
    def __init__(self, name, value):
        self.name = name
        self.value = value

class PropertyBrowser(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Property Browser")
        self.setGeometry(100, 100, 400, 400)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.properties = []

        self.create_widgets()
        self.load_properties_from_file()

    def create_widgets(self):
        self.layout.addWidget(QLabel("속성 이름:"))
        self.property_name_input = QLineEdit(self)
        self.layout.addWidget(self.property_name_input)

        self.layout.addWidget(QLabel("속성 값:"))
        self.property_value_input = QLineEdit(self)
        self.layout.addWidget(self.property_value_input)

        self.property_list = QListWidget(self)
        self.layout.addWidget(self.property_list)

        self.save_button = QPushButton("속성 저장", self)
        self.save_button.clicked.connect(self.save_property)
        self.layout.addWidget(self.save_button)

        self.edit_button = QPushButton("수정", self)
        self.edit_button.clicked.connect(self.edit_property)
        self.layout.addWidget(self.edit_button)

        self.delete_button = QPushButton("삭제", self)
        self.delete_button.clicked.connect(self.delete_property)
        self.layout.addWidget(self.delete_button)

    def save_property(self):
        property_name = self.property_name_input.text()
        property_value = self.property_value_input.text()
        
        new_property = Property(property_name, property_value)
        self.properties.append(new_property)
        self.property_list.addItem(f"{new_property.name} = {new_property.value}")

        self.property_name_input.clear()
        self.property_value_input.clear()
        self.save_properties_to_file()

    def edit_property(self):
        selected_item = self.property_list.currentItem()
        if selected_item:
            index = self.property_list.row(selected_item)
            property_name = self.property_name_input.text()
            property_value = self.property_value_input.text()

            self.properties[index].name = property_name
            self.properties[index].value = property_value
            self.property_list.item(index).setText(f"{property_name} = {property_value}")

            self.property_name_input.clear()
            self.property_value_input.clear()
            self.save_properties_to_file()

    def delete_property(self):
        selected_item = self.property_list.currentItem()
        if selected_item:
            index = self.property_list.row(selected_item)
            self.properties.pop(index)
            self.property_list.takeItem(index)
            self.save_properties_to_file()

    def save_properties_to_file(self):
        with open("properties.json", "w") as f:
            json.dump([{'name': p.name, 'value': p.value} for p in self.properties], f)

    def load_properties_from_file(self):
        try:
            with open("properties.json", "r") as f:
                properties = json.load(f)
                for prop in properties:
                    self.properties.append(Property(prop['name'], prop['value']))
                    self.property_list.addItem(f"{prop['name']} = {prop['value']}")
        except FileNotFoundError:
            print("파일을 찾을 수 없습니다.")

if __name__ == "__main__":
    app = QApplication([])
    window = PropertyBrowser()
    window.show()
    app.exec_()

10. 결론

이번 강좌에서는 PyQt를 사용하여 속성 관리 UI를 구현하는 방법에 대해 알아보았습니다. Property Browser를 통해 사용자 인터페이스가 어떻게 보다 직관적이고 사용하기 쉽게 변할 수 있는지 살펴보았습니다. 또한, 속성 추가, 수정 및 삭제 기능을 구현하여 사용자 경험을 개선할 수 있는 방법을 알아보았습니다.

이와 같은 방식으로 다양한 속성을 관리하는 UI를 구축하여 애플리케이션의 효율성을 높이는데 기여할 수 있습니다. 더 나아가 추가적인 기능을 구현하여 사용자의 요구에 맞는 맞춤형 애플리케이션을 개발할 수 있습니다.

향후 이 강좌에서 배운 내용을 바탕으로 더욱 발전된 PyQt 애플리케이션을 개발해보시기 바랍니다. 감사합니다!