Basic GUI controls

Create interactive controls like sliders, buttons, and text inputs.

This example demonstrates the full range of GUI controls available in viser, including:

Input Controls:

Interactive Elements:

Layout & Organization:

The example shows how to read control values with .value, manage visibility with .visible, and disable controls with .disabled. GUI state automatically synchronizes with all connected clients.

Source: examples/02_gui/00_basic_controls.py

Basic GUI controls

Code

  1import time
  2
  3import numpy as np
  4
  5import viser
  6
  7
  8def main() -> None:
  9    server = viser.ViserServer()
 10
 11    # Add some common GUI elements: number inputs, sliders, vectors, checkboxes.
 12    with server.gui.add_folder("Read-only"):
 13        gui_counter = server.gui.add_number(
 14            "Counter",
 15            initial_value=0,
 16            disabled=True,
 17        )
 18        gui_slider = server.gui.add_slider(
 19            "Slider",
 20            min=0,
 21            max=100,
 22            step=1,
 23            initial_value=0,
 24            disabled=True,
 25        )
 26        gui_progress = server.gui.add_progress_bar(25, animated=True)
 27
 28    with server.gui.add_folder("Editable"):
 29        gui_vector2 = server.gui.add_vector2(
 30            "Position",
 31            initial_value=(0.0, 0.0),
 32            step=0.1,
 33        )
 34        gui_vector3 = server.gui.add_vector3(
 35            "Size",
 36            initial_value=(1.0, 1.0, 1.0),
 37            step=0.25,
 38        )
 39        with server.gui.add_folder("Text toggle"):
 40            gui_checkbox_hide = server.gui.add_checkbox(
 41                "Hide",
 42                initial_value=False,
 43            )
 44            gui_text = server.gui.add_text(
 45                "Text",
 46                initial_value="Hello world",
 47            )
 48            gui_button = server.gui.add_button("Button", icon=viser.Icon.MOUSE)
 49            gui_checkbox_disable = server.gui.add_checkbox(
 50                "Disable",
 51                initial_value=False,
 52            )
 53            gui_rgb = server.gui.add_rgb(
 54                "Color",
 55                initial_value=(255, 255, 0),
 56            )
 57            gui_multi_slider = server.gui.add_multi_slider(
 58                "Multi slider",
 59                min=0,
 60                max=100,
 61                step=1,
 62                initial_value=(0, 30, 100),
 63                marks=((0, "0"), (50, "5"), (70, "7"), 99),
 64            )
 65            gui_slider_positions = server.gui.add_slider(
 66                "# sliders",
 67                min=0,
 68                max=10,
 69                step=1,
 70                initial_value=3,
 71                marks=((0, "0"), (5, "5"), (7, "7"), 10),
 72            )
 73            gui_upload_button = server.gui.add_upload_button(
 74                "Upload", icon=viser.Icon.UPLOAD
 75            )
 76
 77    @gui_upload_button.on_upload
 78    def _(_) -> None:
 79        file = gui_upload_button.value
 80        print(file.name, len(file.content), "bytes")
 81
 82    # Pre-generate a point cloud to send.
 83    point_positions = np.random.uniform(low=-1.0, high=1.0, size=(5000, 3))
 84    color_coeffs = np.random.uniform(0.4, 1.0, size=(point_positions.shape[0]))
 85
 86    counter = 0
 87    while True:
 88        # We can set the value of an input to a particular value. Changes are
 89        # automatically reflected in connected clients.
 90        gui_counter.value = counter
 91        gui_slider.value = counter % 100
 92
 93        # We can set the position of a scene node with `.position`, and read the value
 94        # of a gui element with `.value`. Changes are automatically reflected in
 95        # connected clients.
 96        server.scene.add_point_cloud(
 97            "/point_cloud",
 98            points=point_positions * np.array(gui_vector3.value, dtype=np.float32),
 99            colors=(np.array(gui_rgb.value) * color_coeffs[:, None]).astype(np.uint8),
100            position=gui_vector2.value + (0,),
101            point_shape="circle",
102        )
103        gui_button.color = gui_rgb.value
104
105        gui_progress.value = float((counter % 100))
106
107        # We can use `.visible` and `.disabled` to toggle GUI elements.
108        gui_text.visible = not gui_checkbox_hide.value
109        gui_button.visible = not gui_checkbox_hide.value
110        gui_rgb.disabled = gui_checkbox_disable.value
111        gui_multi_slider.disabled = gui_checkbox_disable.value
112        gui_slider_positions.disabled = gui_checkbox_disable.value
113        gui_button.disabled = gui_checkbox_disable.value
114        gui_upload_button.disabled = gui_checkbox_disable.value
115
116        # Update the number of handles in the multi-slider.
117        if gui_slider_positions.value != len(gui_multi_slider.value):
118            gui_multi_slider.value = np.linspace(
119                0, 100, gui_slider_positions.value, dtype=np.int64
120            )
121
122        counter += 1
123        time.sleep(0.01)
124
125
126if __name__ == "__main__":
127    main()