Base Elements

Base Elements#

Base Elements are the building blocks for an Edifice application.

Each Base Element manages an underlying QWidget.

If the Base Element is a layout, then it also manages an underlying QLayout, and it can have children.

When the base Element renders, it adjusts the properties of the underlying QWidget and QLayout.

All Elements in this module inherit from QtWidgetElement and its props, such as style and on_click. This means that all Elements can respond to clicks and are stylable using style prop and Qt Style Sheets.

Base Element can roughly be divided into layout Elements and leaf Elements.

Layout Elements take a list of children and function as a container for its children; it is most analogous to the <div> html tag. The two basic layout components are View and ScrollView. They take a layout prop, which controls whether children are laid out in a row, a column, or without any preset layout. A layout component without children will appear as an empty spot in the window; of course, you could still set the background color, borders, and size, making this a handy way of reserving blank spot on the screen or drawing an empty rectangle.

Content components display some information or control on the window. The basic component for displaying text is Label, which simply displays the given text (or any Python object). The font can be controlled using the style prop. The Icon component is another handy component, displaying an icon from the Font Awesome icon set. Finally, the Button and TextInput components allow you to collect input from the user.

QtWidgetElement([style, tool_tip, cursor, ...])

Base Qt Widget.

Window([title, icon, menu, on_close])

The root View element of an App which runs in an operating system window.

ExportList()

The root element for an App which does App.export_widgets().

View([layout])

Basic layout widget for grouping children together.

ScrollView([layout])

Scrollable layout widget for grouping children together.

TabView([labels])

Widget with multiple tabs.

GridView([layout, key_to_code])

Grid layout widget for rendering children on a 2D rectangular grid.

TableGridView([row_stretch, column_stretch, ...])

Table-style grid layout displays its children as aligned rows of columns.

FlowView(**kwargs)

Flow-style layout widget.

Label([text, selectable, editable, ...])

Basic widget for displaying text.

Image(src[, aspect_ratio_mode])

An image container.

ImageSvg(src, **kwargs)

An SVG Image container.

Icon(name[, size, collection, ...])

Display an Icon.

IconButton(name[, size, collection, ...])

Display an Icon Button.

Button([title])

Basic button widget.

ButtonView([layout, on_trigger])

A Button where the label is the Button’s children rendered in a edifice.View.

TextInput([text, placeholder_text, ...])

Basic widget for a one line text input.

SpinInput([value, min_value, max_value, ...])

Widget for a int input value with up/down buttons.

CheckBox([checked, text, on_change])

Checkbox widget.

RadioButton([checked, text, on_change])

Radio buttons.

Slider(value[, min_value, max_value, ...])

Slider bar widget.

ProgressBar(value[, min_value, max_value, ...])

Progress bar widget.

Dropdown([selection, text, options, ...])

Basic widget for a dropdown menu.

Events#

For every base Element, user interactions generate events, and you can specify how to handle the event by passing a callback function (which is either a function or an asyncio coroutine). These callbacks can be passed into the base Element as props, for example the on_click callback that can be passed to every widget, or the on_change callback for checkboxes, radio buttons, sliders, and text input. The callback function is passed an argument describing the event, for example a click object holding click information (location of cursor, etc) or the new value of the input.

These callbacks run in the same thread as the main application. This is handy, as you don’t have to worry about locking and race conditions. However, a lengthy operation will block the application from interacting with the user, which is generally a bad user experience. For such cases, you can use an asyncio coroutine.

Consider this code:

@component
def MyComponent(self):

    results, set_results = use_state("")
    counter, set_counter = use_state(0)

    def on_click(event:QMouseEvent):
        r = fetch_from_network()
        set_results(r)

    with edifice.View():
        edifice.Label(results)
        edifice.Label(counter)
        edifice.Button("Fetch", on_click=on_click)
        edifice.Button("Increment", on_click=lambda e: set_counter(counter + 1)

When the Fetch button is clicked, the event handler will call a lengthy fetch_from_network function, blocking the application from further progress. In the mean time, if the user clicks the increment button, nothing will happen until the fetch is complete.

To allow the rest of the application to run while the fetch is happening, you can define the on_click handler as a coroutine:

@component
def MyComponent(self):

    results, set_results = use_state("")
    counter, set_counter = use_state(0)
    loading, set_loading = use_state(False)

    async def on_click(event:QMouseEvent):
        set_loading(True)
        r = await fetch_from_network()
        set_results(r)
        set_loading(False)

    with edifice.View():
        edifice.Label(results)
        if loading:
            edifice.Label("Loading")
        edifice.Label(counter)
        edifice.Button("Fetch", on_click=on_click)
        edifice.Button("Increment", on_click=lambda e: set_counter(counter + 1)

While the fetch_from_network function is running, control is returned to the event loop, allowing the application to continue handling button clicks.

See docs for QtWidgetElement for a list of supported events.

Custom Widgets#

Not all widgets are currently supported by Edifice. Edifice provides CustomWidget to allow you to bind arbitrary QtWidgets to an Edifice Element.

CustomWidget()

Custom widgets that you can define.