PySide6 Renderer
The PySideRenderer maps template tags to PySide6 (Qt for Python) widgets.
Setup
import collagraph as cg
from PySide6 import QtWidgets
app = QtWidgets.QApplication()
gui = cg.Collagraph(renderer=cg.PySideRenderer())
gui.render(MyComponent, app)
app.exec()
Available Elements
Template tags map to Qt widget classes. There are common short names available:
| Tag | Qt Class |
|---|---|
<window> |
QMainWindow |
<widget> |
QWidget |
<button> |
QPushButton |
<label> |
QLabel |
<lineedit> |
QLineEdit |
<textedit> |
QTextEdit |
<checkbox> |
QCheckBox |
<radiobutton> |
QRadioButton |
<combobox> |
QComboBox |
<slider> |
QSlider |
<spinbox> |
QSpinBox |
<progressbar> |
QProgressBar |
<groupbox> |
QGroupBox |
<tabwidget> |
QTabWidget |
<scrollarea> |
QScrollArea |
<dock> |
QDockWidget |
<toolbar> |
QToolBar |
<menubar> |
QMenuBar |
<menu> |
QMenu |
<action> |
QAction |
<statusbar> |
QStatusBar |
<treeview> |
QTreeView |
<treewidget> |
QTreeWidget |
<treewidgetitem> |
QTreeWidgetItem |
<dialogbuttonbox> |
QDialogButtonBox |
Name Lookup from Qt Modules
Beyond the short names above, you can use any class from QtWidgets, QtGui, QtCore, or QtCore.Qt directly by name. Tag names in templates must be lower-case (the lookup is case-insensitive):
You can also use dot notation for nested types:
This means you rarely need to call register_element() -- most Qt classes are available out of the box.
Attributes
Attributes map to setter methods on the Qt widget. The attribute name is converted from kebab-case to the appropriate Qt method:
<label text="Hello" /> <!-- calls setText("Hello") -->
<window title="My App" /> <!-- calls setWindowTitle("My App") -->
<button enabled="false" /> <!-- calls setEnabled(False) -->
Multi-word attribute names may be written with either dashes or underscores; both map to the same camel-cased setter:
<widget maximum-size="(200, 100)" /> <!-- calls setMaximumSize((200, 100)) -->
<widget maximum_size="(200, 100)" /> <!-- same setter -->
<widget window_title="My App" /> <!-- calls setWindowTitle("My App") -->
In Python views, attribute names are keyword arguments, so only the underscore form works (maximum_size=(200, 100)).
Dynamic attributes use Python expressions:
Text Content
Widgets that display text can take their text as element content, including {{ }} interpolation:
This is supported for QLabel and all QAbstractButton subclasses (<button>, <checkbox>, <radiobutton>, ...). The joined content of all text children is displayed through the widget's setText() method, so text can be mixed with directives:
For other widgets, set text via the text attribute instead:
Layouts
Child widgets are laid out using layout elements:
<widget layout="hbox"> <!-- QHBoxLayout -->
<button text="Left" />
<button text="Right" />
</widget>
<widget layout="vbox"> <!-- QVBoxLayout -->
<label text="Top" />
<label text="Bottom" />
</widget>
<widget layout="grid"> <!-- QGridLayout -->
<label text="A" row="0" column="0" />
<label text="B" row="0" column="1" />
</widget>
<widget layout="form"> <!-- QFormLayout -->
<label text="Name:" />
<lineedit />
</widget>
Events
Events map to Qt signals. Use the signal name in snake_case:
<button @clicked="handle_click" />
<lineedit @text_edited="handle_text" />
<slider @value_changed="handle_value" />
<combobox @current_index_changed="handle_index" />
Tree Views
Tree views and tree widgets work well with reactive state:
- Keyed reorders preserve UI state. When items in a
v-forwith:keyare reordered (reversed, shuffled, sorted), the selection and expansion state of tree items moves along with them. Seeexamples/pyside/keyed_tree_demo.cgx. - Drag and drop is supported. Drops can be turned into state mutations, with selection and expansion state preserved across the resulting re-render. See
examples/pyside/tree_dnd_example.cgxfor a complete example with a custom drop-awareQTreeWidget.
Registering Custom Elements
You can register additional Qt classes:
from PySide6 import QtWidgets
from collagraph.renderers.pyside_renderer import PySideRenderer
PySideRenderer.register_element("calendar", QtWidgets.QCalendarWidget)
Then use in templates: