.. note::
    :class: sphx-glr-download-link-note

    Click :ref:`here <sphx_glr_download_auto_tutorials_02_ui_viz_ui.py>` to download the full example code
.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_tutorials_02_ui_viz_ui.py:


===============
User Interfaces
===============

This example shows how to use the UI API. We will demonstrate how to create
several FURY UI elements, then use a list box to toggle which element is shown.

First, a bunch of imports.


.. code-block:: default


    from fury.data import read_viz_icons, fetch_viz_icons
    from fury import ui, window, actor
    import numpy as np







Shapes
======

Let's start by drawing some simple shapes. First, a rectangle.


.. code-block:: default


    rect = ui.Rectangle2D(size=(200, 200), position=(400, 300), color=(1, 0, 1))







Then we can draw a solid circle, or disk.


.. code-block:: default


    disk = ui.Disk2D(outer_radius=50, center=(500, 500), color=(1, 1, 0))







Add an inner radius to make a ring.


.. code-block:: default


    ring = ui.Disk2D(outer_radius=50, inner_radius=45, center=(500, 300),
                     color=(0, 1, 1))







Image
=====

Now let's display an image. First we need to fetch some icons that are
included in FURY.


.. code-block:: default


    fetch_viz_icons()





.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none

    Data size is approximately 12KB
    Dataset is already in place. If you want to fetch it again please first remove the folder /Users/koudoro/.fury/icons 



Now we can create an image container.


.. code-block:: default


    img = ui.ImageContainer2D(img_path=read_viz_icons(fname='home3.png'),
                              position=(450, 350))







Panel with buttons and text
===========================

Let's create some buttons and text and put them in a panel. First we'll
make the panel.


.. code-block:: default


    panel = ui.Panel2D(size=(300, 150), color=(1, 1, 1), align="right")
    panel.center = (500, 400)







Then we'll make two text labels and place them on the panel.
Note that we specifiy the position with integer numbers of pixels.


.. code-block:: default


    text = ui.TextBlock2D(text='Click me')
    text2 = ui.TextBlock2D(text='Me too')
    panel.add_element(text, (50, 100))
    panel.add_element(text2, (180, 100))







Then we'll create two buttons and add them to the panel.

Note that here we specify the positions with floats. In this case, these are
percentages of the panel size.


.. code-block:: default



    button_example = ui.Button2D(
        icon_fnames=[('square', read_viz_icons(fname='stop2.png'))])

    icon_files = []
    icon_files.append(('down', read_viz_icons(fname='circle-down.png')))
    icon_files.append(('left', read_viz_icons(fname='circle-left.png')))
    icon_files.append(('up', read_viz_icons(fname='circle-up.png')))
    icon_files.append(('right', read_viz_icons(fname='circle-right.png')))

    second_button_example = ui.Button2D(icon_fnames=icon_files)

    panel.add_element(button_example, (0.25, 0.33))
    panel.add_element(second_button_example, (0.66, 0.33))







We can add a callback to each button to perform some action.


.. code-block:: default



    def change_text_callback(i_ren, _obj, _button):
        text.message = 'Clicked!'
        i_ren.force_render()


    def change_icon_callback(i_ren, _obj, _button):
        _button.next_icon()
        i_ren.force_render()


    button_example.on_left_mouse_button_clicked = change_text_callback
    second_button_example.on_left_mouse_button_pressed = change_icon_callback







Cube and sliders
================

Let's add a cube to the scene and control it with sliders.


.. code-block:: default



    cube = actor.cube(centers=np.array([[15, 0, 0]]),
                      colors=np.array([[0, 0, 1]]),
                      scales=np.array([[20, 20, 20]]),
                      directions=np.array([[0, 0, 1]]))







Now we'll add three sliders: one circular and two linear.


.. code-block:: default


    ring_slider = ui.RingSlider2D(center=(740, 400), initial_value=0,
                                  text_template="{angle:5.1f}°")

    line_slider_x = ui.LineSlider2D(center=(500, 250), initial_value=0,
                                    min_value=-10, max_value=10,
                                    orientation="horizontal")

    line_slider_y = ui.LineSlider2D(center=(650, 350), initial_value=0,
                                    min_value=-10, max_value=10,
                                    orientation="vertical")







We can use a callback to rotate the cube with the ring slider.


.. code-block:: default



    def rotate_cube(slider):
        angle = slider.value
        previous_angle = slider.previous_value
        rotation_angle = angle - previous_angle
        cube.RotateX(rotation_angle)


    ring_slider.on_change = rotate_cube







Similarly, we can translate the cube with line sliders.
We use global variables to keep track of the position of the cube.


.. code-block:: default


    cube_x = 0
    cube_y = 0


    def translate_cube_x(slider):
        global cube_x, cube_y
        cube_x = slider.value
        cube.SetPosition(cube_x, cube_y, 0)


    def translate_cube_y(slider):
        global cube_x, cube_y
        cube_y = slider.value
        cube.SetPosition(cube_x, cube_y, 0)


    line_slider_x.on_change = translate_cube_x
    line_slider_y.on_change = translate_cube_y







Range Slider
============

Finally, we can add a range slider. This element is composed of two sliders.
The first slider has two handles which let you set the range of the second.


.. code-block:: default


    range_slider_x = ui.RangeSlider(
        line_width=8, handle_side=25, range_slider_center=(450, 450),
        value_slider_center=(450, 350), length=150, min_value=0,
        max_value=10, font_size=18, range_precision=2, value_precision=4,
        shape="square")

    range_slider_y = ui.RangeSlider(
        line_width=8, handle_side=25, range_slider_center=(750, 400),
        value_slider_center=(650, 400), length=150, min_value=0,
        max_value=10, font_size=18, range_precision=2, value_precision=4,
        orientation="vertical", shape="square")






Select menu
============

We just added many examples. If we showed them all at once, they would fill
the screen. Let's make a simple menu to choose which example is shown.

We'll first make a list of the examples.


.. code-block:: default


    examples = [[rect], [disk, ring], [img], [panel],
                [ring_slider, line_slider_x, line_slider_y],
                [range_slider_x, range_slider_y]]







Now we'll make a function to hide all the examples. Then we'll call it so
that none are shown initially.


.. code-block:: default



    def hide_all_examples():
        for example in examples:
            for element in example:
                element.set_visibility(False)
        cube.SetVisibility(False)


    hide_all_examples()







To make the menu, we'll first need to create a list of labels which
correspond with the examples.


.. code-block:: default


    values = ['Rectangle', 'Disks', 'Image', "Button Panel",
              "Line & Ring Slider", "Range Slider"]







Now we can create the menu.


.. code-block:: default


    listbox = ui.ListBox2D(values=values, position=(10, 300), size=(300, 200),
                           multiselection=False)







Then we will use a callback to show the correct example when a label is
clicked.


.. code-block:: default



    def display_element():
        hide_all_examples()
        example = examples[values.index(listbox.selected[0])]
        for element in example:
            element.set_visibility(True)
        if values.index(listbox.selected[0]) == 4:
            cube.SetVisibility(True)


    listbox.on_change = display_element







Show Manager
==================================

Now that all the elements have been initialised, we add them to the show
manager.


.. code-block:: default


    current_size = (800, 800)
    show_manager = window.ShowManager(size=current_size, title="FURY UI Example")

    show_manager.scene.add(listbox)
    for example in examples:
        for element in example:
            show_manager.scene.add(element)
    show_manager.scene.add(cube)
    show_manager.scene.reset_camera()
    show_manager.scene.set_camera(position=(0, 0, 200))
    show_manager.scene.reset_clipping_range()
    show_manager.scene.azimuth(30)

    # To interact with the UI, set interactive = True
    interactive = False

    if interactive:
        show_manager.start()

    window.record(show_manager.scene, size=current_size, out_path="viz_ui.png")



.. image:: /auto_tutorials/02_ui/images/sphx_glr_viz_ui_001.png
    :class: sphx-glr-single-img





.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  0.206 seconds)


.. _sphx_glr_download_auto_tutorials_02_ui_viz_ui.py:


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download

     :download:`Download Python source code: viz_ui.py <viz_ui.py>`



  .. container:: sphx-glr-download

     :download:`Download Jupyter notebook: viz_ui.ipynb <viz_ui.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_