dhxpyt API documentation

7 min read Original article ↗

dhxpyt

DHX PyTincture Widgetset Logo

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.

pyTincture on GitHub · dhxpyt on GitHub · pyTincture slides

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"