-
-
Notifications
You must be signed in to change notification settings - Fork 0
COMPONENTS
Zuko edited this page Jan 29, 2026
·
1 revision
Tất cả UI components trong App nên tuân theo pattern nhất quán với:
- File
.uicho giao diện (Qt Designer) - File
Widget.pycho logic UI và Controller - File
Handler.pycho xử lý events (Observer pattern)
- UI logic (Widget) tách biệt với business logic (Handler)
- Dễ maintain và test từng layer riêng biệt
- Tất cả components tuân theo cùng một pattern
- Developer dễ hiểu và implement
- Loose coupling giữa UI và logic
- Dễ extend và modify behavior
- UI được thiết kế bằng visual tool
- Tự động compile và sync
- Components có thể tái sử dụng ở nhiều nơi
- Parameterizable và configurable
# Tạo thư mục component
mkdir windows/components/MyComponent
# Tạo các files cần thiết:
# - MyComponent.ui (Qt Designer)
# - MyComponent.py (compiled UI)
# - MyComponentWidget.py (Widget + Controller)
# - MyComponentHandler.py (Event Handler)
# - __init__.py (Module exports)<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>Zuko</author>
<class>MyComponent</class>
<widget class="QWidget" name="MyComponent">
<!-- UI elements here -->
</widget>
</ui># Manual compile (nếu có pyside6-uic)
pyside6-uic MyComponent.ui -o MyComponent.py
# Hoặc dùng script
python scripts/compile_ui.pyfrom core import BaseController
from .MyComponent import Ui_MyComponent
# QUAN TRỌNG: thứ tự kế thừa BaseController luôn đứng sau Ui, đứng trước Window hoặc Widget của QT
class MyComponentWidget(Ui_MyComponent, BaseController, QWidget):
# Observer pattern mapping
slot_map = {
'buttonClicked': ['myButton', 'clicked'],
}
# External signals
dataChanged = Signal(dict)
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
# Setup logic herefrom core.Observer import Subscriber
class MyComponentHandler(Subscriber):
def __init__(self, widget, events):
super().__init__(events)
self.widget = widget
def onButtonClicked(self, data=None):
# Handle event here
passfrom windows.components.MyComponent import MyComponentWidget
class ParentController(BaseController):
slot_map = {
'data_changed': ['my_comp', 'dataChanged'],
}
def setup_components(self):
# Tạo widget
self.my_comp = MyComponentWidget(parent=self)
self.layout.addWidget(self.my_comp)- Sử dụng meaningful object names
- Set tooltips và status tips
- Configure sane defaults
-
ComponentName.ui- UI definition -
ComponentName.py- Generated UI code (DON'T EDIT) -
ComponentNameWidget.py- Widget implementation -
ComponentNameHandler.py- Event handler -
__init__.py- Module exports
- Kế thừa:
Ui_ComponentName,BaseController,QWidget. Đúng thứ tự - Định nghĩa
slot_mapđầy đủ
- Kế thừa từ
Subscriber - Prefix methods với
on - Handle exceptions properly
- Log important events
- Keep methods focused
def test_component_widget():
widget = MyComponentWidget()
assert widget.some_property == expected_value
def test_component_handler():
widget = MyComponentWidget()
handler = MyComponentHandler(widget, widget.events)
handler.on_some_event()
# Assert expected behaviordef test_component_integration():
parent = ParentController()
parent.setup_components()
# Test component interaction