-
-
Notifications
You must be signed in to change notification settings - Fork 0
05 widget management
Zuko edited this page Jan 21, 2026
·
1 revision
Simplified widget access với dot notation, signal suppression, và config persistence
WidgetManager cung cấp utilities để:
- Dot-notation widget access (
get('parent.child')) - Signal suppression during updates
- Config persistence (save/load widget state)
- Type-safe widget value access
# Via controller
self.widgetManager.get('widgetName')
self.widgetManager.get('parent.child.widget')self.widgetManager.set('widgetName', value, saveToConfig=False)self.widgetManager.load('widgetName', default=None)self.widgetManager.doActionSuppressSignal('widgetName', lambda w: w.setValue(50))from core import BaseController, BaseCtlHandler
class MyControllerHandler(BaseCtlHandler):
def onSaveClicked(self):
# Get widget
input = self.widgetManager.get('usernameInput')
text = input.text()
# Nested access
nestedWidget = self.widgetManager.get('parent.child.widget')class MyHandler(BaseCtlHandler):
def onLoadData(self):
# Set QLineEdit
self.widgetManager.set('nameInput', 'John Doe')
# Set QSpinBox
self.widgetManager.set('ageSpinBox', 25)
# Set QCheckBox
self.widgetManager.set('agreeCheckbox', True)class SettingsHandler(BaseCtlHandler):
def onSaveSettings(self):
# Save to config
self.widgetManager.set('themeComboBox', 'dark', saveToConfig=True)
self.widgetManager.set('autoSaveCheckbox', True, saveToConfig=True)
def onLoadSettings(self):
# Load from config
self.widgetManager.load('themeComboBox', default='light')
self.widgetManager.load('autoSaveCheckbox', default=False)Config key format: {ControllerName}.{widgetName}
Example: MainController.themeComboBox
class MyHandler(BaseCtlHandler):
def updateSliderWithoutSignal(self):
# Suppress valueChanged signal
self.widgetManager.doActionSuppressSignal(
'volumeSlider',
lambda slider: slider.setValue(75)
)
# Or with widget parameter
def updateWidget(widget):
widget.setValue(75)
widget.setEnabled(False)
self.widgetManager.doActionSuppressSignal('volumeSlider', updateWidget)QSpinBox / QDoubleSpinBox:
self.widgetManager.set('spinBox', 42) # Calls setValue()
value = self.widgetManager.get('spinBox').value()QLineEdit / QLabel:
self.widgetManager.set('lineEdit', 'text') # Calls setText()
text = self.widgetManager.get('lineEdit').text()QCheckBox / QRadioButton:
self.widgetManager.set('checkbox', True) # Calls setChecked()
checked = self.widgetManager.get('checkbox').isChecked()# Use descriptive widget names
self.widgetManager.get('usernameInput')
self.widgetManager.get('saveButton')
# Use dot notation for nested widgets
self.widgetManager.get('settingsPanel.themeComboBox')
# Suppress signals when programmatically updating
self.widgetManager.doActionSuppressSignal('slider', lambda w: w.setValue(50))
# Save important settings to config
self.widgetManager.set('theme', 'dark', saveToConfig=True)
# Load with defaults
self.widgetManager.load('theme', default='light')# Don't use set() with dot notation
self.widgetManager.set('parent.child', value) # NotImplementedError
# Don't forget signal suppression for programmatic updates
slider = self.widgetManager.get('slider')
slider.setValue(50) # Triggers valueChanged signal!
# Don't access widgets before setupUi
class MyController(BaseController):
def __init__(self):
super().__init__()
widget = self.widgetManager.get('button') # Error! setupUi not calledclass FormHandler(BaseCtlHandler):
def collectFormData(self):
return {
'name': self.widgetManager.get('nameInput').text(),
'age': self.widgetManager.get('ageSpinBox').value(),
'email': self.widgetManager.get('emailInput').text(),
'subscribe': self.widgetManager.get('subscribeCheckbox').isChecked()
}class DataHandler(BaseCtlHandler):
def loadUserData(self, userData):
# Suppress all signals during batch update
widgets = {
'nameInput': userData['name'],
'ageSpinBox': userData['age'],
'emailInput': userData['email']
}
for widgetName, value in widgets.items():
self.widgetManager.doActionSuppressSignal(
widgetName,
lambda w, v=value: self._setValue(w, v)
)
def _setValue(self, widget, value):
if hasattr(widget, 'setText'):
widget.setText(str(value))
elif hasattr(widget, 'setValue'):
widget.setValue(value)class SettingsController(BaseController, QWidget):
slot_map = {
'saveClicked': ['saveButton', 'clicked'],
'loadClicked': ['loadButton', 'clicked']
}
class SettingsHandler(BaseCtlHandler):
SETTINGS_WIDGETS = ['theme', 'language', 'autoSave', 'fontSize']
def onSaveClicked(self):
for widget in self.SETTINGS_WIDGETS:
value = self._getWidgetValue(widget)
self.widgetManager.set(widget, value, saveToConfig=True)
def onLoadClicked(self):
for widget in self.SETTINGS_WIDGETS:
self.widgetManager.load(widget)
def _getWidgetValue(self, widgetName):
widget = self.widgetManager.get(widgetName)
if hasattr(widget, 'text'):
return widget.text()
elif hasattr(widget, 'value'):
return widget.value()
elif hasattr(widget, 'isChecked'):
return widget.isChecked()- BaseController - Controller integration
- Config - Config persistence
- Common Use Cases - Practical examples