UI Integration
Examples of building reactive forms with pyqt-reactive.
Basic Form Generation
Create a form from a dataclass:
from dataclasses import dataclass
from PyQt6.QtWidgets import QApplication
from pyqt_reactive.forms import ParameterFormManager
@dataclass
class ProcessingConfig:
input_path: str = ""
output_path: str = ""
num_workers: int = 4
enable_gpu: bool = False
threshold: float = 0.5
app = QApplication([])
# Create form from dataclass
form = ParameterFormManager(ProcessingConfig)
form.show()
# Collect values back as typed dataclass
config = form.collect_values()
print(f"Config: {config}")
app.exec()
Form with ObjectState Integration
Bind a form to ObjectState for lazy configuration and inheritance:
from dataclasses import dataclass
from PyQt6.QtWidgets import QApplication
from pyqt_reactive.forms import ParameterFormManager
from objectstate import config_context, ObjectStateRegistry
@dataclass
class GlobalConfig:
threshold: float = 0.5
iterations: int = 10
@dataclass
class StepConfig:
threshold: float = None # Inherit from global
iterations: int = None # Inherit from global
name: str = "step_0"
app = QApplication([])
# Setup ObjectState context
global_cfg = GlobalConfig(threshold=0.7, iterations=20)
with config_context(global_cfg):
# Create form - fields with None will show inherited values as placeholders
form = ParameterFormManager(StepConfig)
form.show()
# Placeholder text shows: "0.7 (from GlobalConfig)"
# User can override by entering a value
app.exec()
Reactive Field Updates
Use FieldChangeDispatcher to react to field changes:
from dataclasses import dataclass
from PyQt6.QtWidgets import QApplication
from pyqt_reactive.forms import ParameterFormManager
from pyqt_reactive.services import FieldChangeDispatcher
@dataclass
class ImageConfig:
width: int = 512
height: int = 512
aspect_ratio: str = "1:1"
app = QApplication([])
form = ParameterFormManager(ImageConfig)
dispatcher = FieldChangeDispatcher()
# React to width changes
def on_width_changed(event):
print(f"Width changed to {event.value}")
# Update aspect ratio or height
dispatcher.subscribe("width", on_width_changed)
form.show()
app.exec()
Theming and Styling
Apply themes to forms:
from dataclasses import dataclass
from PyQt6.QtWidgets import QApplication
from pyqt_reactive.forms import ParameterFormManager
from pyqt_reactive.theming import ColorScheme, apply_theme
@dataclass
class AppConfig:
name: str = "MyApp"
debug: bool = False
app = QApplication([])
form = ParameterFormManager(AppConfig)
# Apply dark theme
apply_theme(form, ColorScheme.DARK)
form.show()
app.exec()
Flash Animations
Visual feedback when values change:
from dataclasses import dataclass
from PyQt6.QtWidgets import QApplication
from pyqt_reactive.forms import ParameterFormManager
@dataclass
class Config:
value: float = 0.5
app = QApplication([])
form = ParameterFormManager(Config)
# Flash animations automatically trigger on value changes
# Provides visual feedback similar to React component updates
form.show()
app.exec()
Window Management
Manage multiple windows with WindowManager:
from dataclasses import dataclass
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton
from pyqt_reactive.services import WindowManager
from pyqt_reactive.forms import ParameterFormManager
@dataclass
class Config:
name: str = "default"
class ConfigWindow(QMainWindow):
def __init__(self, scope_id: str):
super().__init__()
self.scope_id = scope_id
layout = QVBoxLayout()
form = ParameterFormManager(Config)
layout.addWidget(form)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
app = QApplication([])
# Show or focus window
window = WindowManager.show_or_focus(
"config:main",
lambda: ConfigWindow("config:main")
)
# Navigate to specific field
WindowManager.navigate_to("config:main", field="name")
app.exec()
Service Registration
Register custom providers with pyqt-reactive:
from pyqt_reactive.protocols import (
set_form_config,
register_llm_service,
register_codegen_provider,
FormGenConfig
)
# Configure form generation
config = FormGenConfig()
config.log_dir = "/tmp/logs"
set_form_config(config)
# Register custom LLM service
class MyLLMService:
def generate_pipeline(self, description: str) -> str:
return "# Generated pipeline"
register_llm_service(MyLLMService())
# Register custom code generator
class MyCodegenProvider:
def generate_code(self, config) -> str:
return "# Generated code"
register_codegen_provider(MyCodegenProvider())
Custom Widgets
Create custom widgets that work with ParameterFormManager:
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QSlider
from PyQt6.QtCore import Qt, pyqtSignal
from pyqt_reactive.protocols import ValueGettable, ValueSettable
class CustomSliderWidget(QWidget, ValueGettable, ValueSettable):
"""Custom slider widget with label."""
value_changed = pyqtSignal(int)
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.label = QLabel("0")
self.slider = QSlider(Qt.Orientation.Horizontal)
self.slider.setRange(0, 100)
self.slider.valueChanged.connect(self._on_value_changed)
layout.addWidget(self.label)
layout.addWidget(self.slider)
self.setLayout(layout)
def get_value(self):
return self.slider.value()
def set_value(self, value):
self.slider.setValue(int(value))
def _on_value_changed(self, value):
self.label.setText(str(value))
self.value_changed.emit(value)