An editable data table beside a 3D scene¶
Keywords: split view · table · tabular data · TableView
A horizontal split layout: the left pane is a single TableView (an editable
native grid) filling its pane, and the right pane is the 3D SceneView.
Editing a cell echoes the change into the scene's annotation; buttons overlaid
on the scene add rows/columns (TableView.add_row / add_column) and reset
the table.
Run¶
Source¶
viz/ui/controls/table_split.py
Code¶
# SPDX-License-Identifier: Apache-2.0
# Copyright 2021 Christian Perwass
"""table_split.py — An editable data table beside a 3D scene.
A horizontal split layout: the left pane is a single ``TableView`` (an editable
native grid) filling its pane, and the right pane is the 3D ``SceneView``.
Editing a cell echoes the change into the scene's annotation; buttons overlaid
on the scene add rows/columns (``TableView.add_row`` / ``add_column``) and reset
the table.
Run with: uv run python py/examples/viz/ui/controls/table_split.py
Keywords: split view, table, tabular data, TableView
"""
from typing import Any
from pytanga.geometry import Point, Sphere
from pytanga.viz import (
ButtonView,
ControlEvent,
GroupView,
SceneView,
Size,
SplitView,
TableCellChange,
TableColumnAdd,
TableRowAdd,
TableView,
Visualizer,
)
viz = Visualizer(reuse_existing=False, title="Tanga — Table + Scene")
# Main scene content (the default scene, name "").
viz.add(
Sphere(Point(0, 0, 0), radius=2), entity_id="sphere", color="#4488ff", opacity=0.3
)
viz.add(Point(1, 1, 1), color="#ff4444")
_COLUMNS = ["x", "y", "z"]
_ROWS = [["1", "2", "3"], ["4", "5", "6"]]
async def _on_cell(change: TableCellChange, _event: ControlEvent) -> None:
viz.set_annotation(f"Cell ({change.row}, {change.col}) = {change.value!r}")
async def _on_row(add: TableRowAdd, _event: ControlEvent) -> None:
viz.set_annotation(f"Added row {add.row}")
async def _on_column(add: TableColumnAdd, _event: ControlEvent) -> None:
viz.set_annotation(f"Added column {add.col} ({add.header!r})")
async def _on_reset(_value: Any, _event: ControlEvent) -> None:
# `set_value` mutates the control *and* pushes `control_update` (injected at
# mount), so the browser redraws the grid.
table_view.set_value({"columns": _COLUMNS, "rows": _ROWS})
viz.set_annotation("Table reset.")
async def _on_add_row(_value: Any, _event: ControlEvent) -> None:
table_view.add_row()
viz.set_annotation("Added a row.")
async def _on_add_column(_value: Any, _event: ControlEvent) -> None:
table_view.add_column(f"C{len(table_view.columns) + 1}")
viz.set_annotation("Added a column.")
table_view = TableView(
"data",
label="Data",
columns=_COLUMNS,
rows=_ROWS,
on_cell_change=_on_cell,
on_row_add=_on_row,
on_column_add=_on_column,
)
layout = SplitView(
orientation="horizontal",
sizes=[Size.percent(40), Size.percent(60)],
children=[
table_view,
SceneView(
"",
overlay=[
GroupView(
"Actions",
[
ButtonView("btn_add_row", label="+ Row", on_click=_on_add_row),
ButtonView(
"btn_add_col", label="+ Column", on_click=_on_add_column
),
ButtonView(
"btn_reset", label="Reset table", on_click=_on_reset
),
],
position="top-left",
),
],
),
],
)
viz.show(layout=layout)
print("Table + scene split view is shown at a single URL. Press Ctrl+C to exit.")
viz.wait()