dhxpyt

Overview
The DHX PyTincture Widgetset is a Python library that integrates DHTMLX JavaScript UI components with the pyTincture framework using Pyodide. It enables building interactive, browser-based user interfaces directly in Python, supporting cross-platform GUI development with rich widgets like grids, charts, and forms.
Features
- Direct integration with DHTMLX UI components
- Pyodide-powered Python execution in the browser
- Cross-platform compatibility
- Customizable and reusable widgets
- Event handling for interactive experiences
Detailed class and API documentation is available in the sidebar.
Installation
Use CPython 3.13 or 3.14. The commands below use 3.13; substitute 3.14 if that is installed. No widgetset repository clone is needed.
pyTincture + DHTMLX quickstart
Three Python files. A real grid, a collapsible sidebar, and working toolbar actions.
Version-matched preview: pyTincture 1.0.0rc6 on the server, dhxpyt 0.9.18 in the browser. Install only pyTincture on the host. The framework supplies Pyodide and loads the pinned widgetset for you; do not add js, pyodide-py, or dhxpyt to this server environment.
Keep all three downloads together: service.py · quickstart.py · widget.py. Run the service command below, not python quickstart.py: that file is browser code.
Windows · PowerShell
mkdir pytincture-quickstart
cd pytincture-quickstart
py -3.13 -m venv .venv
.\.venv\Scripts\python.exe -m pip install "pytincture==1.0.0rc6"
Invoke-WebRequest https://pytincture.com/quickstart/service.py -OutFile service.py
Invoke-WebRequest https://pytincture.com/quickstart.py -OutFile quickstart.py
Invoke-WebRequest https://pytincture.com/quickstart/widget.py -OutFile widget.py
.\.venv\Scripts\python.exe -m uvicorn service:app --host 127.0.0.1 --port 8070
Linux / macOS
mkdir pytincture-quickstart
cd pytincture-quickstart
python3.13 -m venv .venv
.venv/bin/python -m pip install "pytincture==1.0.0rc6"
curl --fail --location --remote-name https://pytincture.com/quickstart/service.py
curl --fail --location --remote-name https://pytincture.com/quickstart.py
curl --fail --location --remote-name https://pytincture.com/quickstart/widget.py
.venv/bin/python -m uvicorn service:app --host 127.0.0.1 --port 8070
Open http://127.0.0.1:8070/quickstart. The first load downloads the browser runtime and widgetset; keep an internet connection available. Opening the service root redirects to the same app.
Try it
- Add item adds a row. Click twice to go from three rows to five.
- Reset data restores the original three rows.
- Toggle menu collapses and expands the sidebar.
- Dark theme / Light theme changes the whole interface.
- Click a column header to sort, or click a row to select it.
This is a local UI demo with in-memory sample data, not a database-backed or authenticated application. Reloading resets the data. Keep the loopback bind shown above, and configure authentication and authorization before adding protected data or exposing an application publicly.
Verify the service
/healthz should report 1.0.0rc6; /readyz should report ready. Both should return HTTP 200.
Checked on macOS with Python 3.13 and Chrome. The Windows commands are provided but have not been executed on Windows. If startup fails, check the named stage in the loading panel and consult the RC6 troubleshooting guide.
The three files
service.py · server
"""Local development service; the UI and widget dependencies run in the browser."""
from pathlib import Path
from pytincture import PytinctureConfig, create_app
HERE = Path(__file__).resolve().parent
app = create_app(
PytinctureConfig(
modules_path=str(HERE),
default_application="quickstart",
)
)
widget.py · browser package declaration
"""Exact browser widgetset version; read without importing browser-only code."""
__widgetset__ = "dhxpyt"
__version__ = "0.9.18"
quickstart.py · complete browser UI and event handlers
"""Browser UI for the pyTincture 1.0.0rc6 + dhxpyt 0.9.18 quickstart."""
import sys
if sys.platform != "emscripten":
raise SystemExit(
"This file runs in the browser. Download service.py and widget.py from "
"https://pytincture.com/dhxpyt.html#quickstart, then run: "
"python -m uvicorn service:app --host 127.0.0.1 --port 8070"
)
import json
import js
import widget
from dhxpyt.grid import GridColumnConfig, GridConfig
from dhxpyt.layout import CellConfig, LayoutConfig, MainWindow
from dhxpyt.sidebar import NavItemConfig, SidebarConfig
from dhxpyt.toolbar import ButtonConfig, ToolbarConfig
SAMPLE_DATA = [
{"id": 1, "name": "Item 1", "value": 100},
{"id": 2, "name": "Item 2", "value": 200},
{"id": 3, "name": "Item 3", "value": 300},
]
class quickstart(MainWindow):
layout_config = LayoutConfig(
type="line",
cols=[
CellConfig(id="sidebar", width="auto"),
CellConfig(id="content"),
],
)
def load_ui(self):
js.document.title = "pyTincture + DHTMLX quickstart"
self.dark = False
self.next_id = 4
self.set_theme("light")
self.sidebar = self.add_sidebar(
id="sidebar",
sidebar_config=SidebarConfig(
width=200,
collapsed=False,
data=[
NavItemConfig(id="toggle", value="Toggle menu", icon="mdi mdi-menu"),
NavItemConfig(id="items", value="Items", icon="mdi mdi-view-list"),
],
),
)
self.sidebar.on_click(self.sidebar_clicked)
self.sidebar.select("items")
content = self.add_layout(
id="content",
layout_config=LayoutConfig(
type="line",
rows=[CellConfig(id="toolbar", height=56), CellConfig(id="grid")],
),
)
self.toolbar = content.add_toolbar(
id="toolbar",
toolbar_config=ToolbarConfig(
data=[
ButtonConfig(id="add", value="Add item", icon="mdi mdi-plus"),
ButtonConfig(id="reset", value="Reset data", icon="mdi mdi-refresh"),
ButtonConfig(id="theme", value="Dark theme", icon="mdi mdi-theme-light-dark"),
]
),
)
self.toolbar.on_click(self.toolbar_clicked)
self.grid = content.add_grid(
id="grid",
grid_config=GridConfig(
columns=[
GridColumnConfig(id="id", type="number", width=90, header=[{"text": "ID"}]),
GridColumnConfig(id="name", header=[{"text": "Name"}]),
GridColumnConfig(id="value", type="number", header=[{"text": "Value"}]),
],
data=[dict(row) for row in SAMPLE_DATA],
autoWidth=True,
selection="row",
),
)
def sidebar_clicked(self, item_id, event):
if item_id == "toggle":
self.sidebar.toggle()
def toolbar_clicked(self, item_id, event):
if item_id == "add":
row = {"id": self.next_id, "name": f"Item {self.next_id}", "value": self.next_id * 100}
self.grid.grid.data.add(js.JSON.parse(json.dumps(row)))
self.next_id += 1
elif item_id == "reset":
self.grid.grid.data.removeAll()
self.grid.grid.data.parse(js.JSON.parse(json.dumps(SAMPLE_DATA)))
self.next_id = 4
elif item_id == "theme":
self.dark = not self.dark
self.set_theme("dark" if self.dark else "light")
self.toolbar.update_item("theme", {"value": "Light theme" if self.dark else "Dark theme"})
Licensing
pyTincture core is MIT licensed. dhxpyt is GPL-2.0 and DHTMLX has separate terms. Closed-source DHTMLX use requires an appropriate commercial license; that license does not automatically relicense dhxpyt. Review both before distributing your app.
The collapsed module source below is an archived API-documentation snapshot. Its embedded quickstart is obsolete; use the RC6 instructions and downloads above.
1""" 2# DHX PyTincture WASM Based Widgetset 3 4<img src="tincture.jpeg" alt="DHX PyTincture Widgetset Logo" width="400" style="display: block; margin: 0 auto;"> 5 6## Overview 7 8The DHX PyTincture Widgetset is a Python library that integrates DHTMLX JavaScript UI components with the pyTincture framework using Pyodide. It enables building interactive, browser-based user interfaces directly in Python, supporting cross-platform GUI development with rich widgets like grids, charts, and forms. 9 10## Features 11 12- Direct integration with DHTMLX UI components 13- Pyodide-powered Python execution in the browser 14- Cross-platform compatibility 15- Customizable and reusable widgets 16- Event handling for interactive experiences 17 18Detailed class and API documentation is available in the sidebar. 19 20## Installation 21 22### Prerequisites 23- Python 3.13+ 24- Pyodide 25 26### Steps 271. Clone the repository: 28 ```bash 29 git clone https://github.com/pytincture/dhx_pytincture_widgetset.git 30 cd dhx_pytincture_widgetset;``` 31 32## QuickStart 33 34## Windows 35#### Install UV / pytincture / dhxpyt on Powershell 36``` 37powershell -c "irm https://astral.sh/uv/install.ps1 | iex" 38$env:Path += ";$env:USERPROFILE\.cargo\bin" 39[Environment]::SetEnvironmentVariable("Path", $env:Path, [System.EnvironmentVariableTarget]::User) 40$env:Path = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) 41New-Item -ItemType Directory -Name dhxpyt_quickstart; Set-Location dhxpyt_quickstart 42uv venv --python 3.13; .\.venv\Scripts\Activate.ps1 43uv pip install dhxpyt pyodide-py js pytincture itsdangerous 44Invoke-WebRequest -Uri https://pytincture.com/quickstart.py -OutFile quickstart.py 45$env:PYTHONUTF8 = "1" 46uv run quickstart.py 47``` 48 49## Linux / MacOS 50#### Install UV / pytincture / dhxpyt on Bash 51``` 52curl -LsSf https://astral.sh/uv/install.sh | sh 53echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc 54source ~/.bashrc 55uv --version 56mkdir dhxpyt_quickstart;cd dhxpyt_quickstart 57uv venv --python 3.13 && source .venv/bin/activate 58uv pip install dhxpyt pyodide-py js pytincture itsdangerous 59curl -O https://pytincture.com/quickstart.py 60uv run quickstart.py 61``` 62 63Open in Browser: 64http://localhost:8070/quickstart 65 66 67### Example Code 68```python 69import sys 70from dhxpyt.layout import MainWindow, Layout, LayoutConfig, CellConfig 71from dhxpyt.toolbar import ButtonConfig, ToolbarConfig 72from dhxpyt.sidebar import NavItemConfig, SidebarConfig 73from dhxpyt.grid import GridConfig, GridColumnConfig 74from pyodide.ffi import create_proxy 75 76# Sample data for the grid 77SAMPLE_DATA = [ 78 {"id": 1, "name": "Item 1", "value": 100}, 79 {"id": 2, "name": "Item 2", "value": 200}, 80 {"id": 3, "name": "Item 3", "value": 300} 81] 82 83class QuickstartMain(Layout): 84 layout_config = LayoutConfig( 85 type="line", 86 cols=[ 87 CellConfig(id="sidebar", width="auto"), 88 CellConfig(id="content") 89 ] 90 ) 91 92 def load_ui(self): 93 # Sidebar configuration 94 sidebar_items = [ 95 NavItemConfig(id="hamburger", icon="mdi mdi-menu"), 96 NavItemConfig(id="items", value="Items", icon="mdi mdi-view-list") 97 ] 98 sidebar_config = SidebarConfig(data=sidebar_items, collapsed=False) 99 self.sidebar = self.add_sidebar(id="sidebar", sidebar_config=sidebar_config) 100 self.sidebar.on_click(create_proxy(self.handle_sidebar_click)) 101 102 # Content layout with toolbar and grid 103 content_layout_config = LayoutConfig( 104 type="line", 105 rows=[ 106 CellConfig(id="toolbar", height="auto"), 107 CellConfig(id="grid") 108 ] 109 ) 110 self.content_layout = self.add_layout("content", content_layout_config) 111 112 # Toolbar configuration 113 toolbar_config = ToolbarConfig(data=[ 114 ButtonConfig(id="add", value="Add Item", icon="mdi mdi-plus"), 115 ButtonConfig(id="refresh", value="Refresh", icon="mdi mdi-refresh") 116 ]) 117 self.toolbar = self.content_layout.add_toolbar(id="toolbar", toolbar_config=toolbar_config) 118 119 # Grid configuration 120 grid_columns = [ 121 GridColumnConfig(id="id", width=100, header=[{"text": "ID"}]), 122 GridColumnConfig(id="name", width=200, header=[{"text": "Name"}]), 123 GridColumnConfig(id="value", width=150, header=[{"text": "Value"}]) 124 ] 125 grid_config = GridConfig(columns=grid_columns, data=SAMPLE_DATA) 126 self.grid = self.content_layout.add_grid(id="grid", grid_config=grid_config) 127 128 def handle_sidebar_click(self, id, event): 129 if id == "hamburger": 130 self.sidebar.toggle() 131 132class QuickstartApp(MainWindow): 133 def load_ui(self): 134 self.set_theme("dark") 135 self.main_layout = QuickstartMain(parent=self) 136 self.attach("mainwindow", self.main_layout.layout) 137 138if __name__ == "__main__" and sys.platform != "emscripten": 139 from pytincture import launch_service 140 launch_service() 141 142``` 143""" 144 145__widgetset__ = "dhxpyt" 146__version__ = "0.8.3" 147__version_tuple__ = tuple(map(int, __version__.split('.'))) 148__description__ = "Python wrapper for DHTMLX widgets"