GUI Concepts#

GUI elements are represented as instances of UIWidget. The GUI is structured like a tree; every widget can have other widgets as children.

The root of the tree is the UIManager. The UIManager connects the user interactions with the GUI. Read more about User-interface events.

Classes of arcade’s GUI code are prefixed with UI- to make them easy to identify and search for in autocompletion.

UIWidget#

The UIWidget class is the core of arcade’s GUI system. Widgets specify the behavior and graphical representation of any UI element, such as buttons or labels.

A UIWidget has following properties.

rect

A tuple with four slots. The first two are x and y coordinates (bottom left of the widget), and the last two are width and height.

children

Child widgets rendered within this widget. A UIWidget will not move or resize its children; use a UILayout instead.

size_hint

A tuple of two normalized floats (0.0-1.0) describing the portion of the parent’s width and height this widget prefers to occupy.

Examples:

# Prefer to take up all space within the parent
widget.size_hint = (1.0, 1.0)

# Prefer to take up the full width & half the height of the parent
widget.size_hint = (1.0, 0.5)
# Prefer using 1/10th of the available width & height
widget.size_hint = (0.1, 0.1)
size_hint_min

A tuple of two integers defining the minimum width and height of the widget. Attempting to set a smaller width or height on the widget will fail by defaulting to the minimum values specified here.

size_hint_max

A tuple of two integers defining the maximum width and height of the widget. Attempting to set a larger width or height greater will fail by defaulting to the to the maximum values specified here.

Warning

Size hints do nothing on their own!

They are hints to UILayout instances, which may choose to use or ignore them.

Rendering#

do_render() is called recursively if rendering was requested via trigger_render(). In case widgets have to request their parents to render, use arcade.gui.UIWidget.trigger_full_render().

The widget has to draw itself and child widgets within do_render(). Due to the deferred functionality render does not have to check any dirty variables, as long as state changes use the trigger_full_render() method.

For widgets, that might have transparent areas, they have to request a full rendering.

Warning

Enforced rendering of the whole GUI might be very expensive!

UILayout#

UILayout are widgets, which reserve the option to move or resize children. They might respect special properties of a widget like size_hint, size_hint_min, or size_hint_max.

The arcade.gui.UILayout only resizes a child’s dimension (x or y axis) if size_hint provides a value for the axis, which is not None for the dimension.

Algorithm#

arcade.gui.UIManager triggers the layout and render process right before the actual frame draw. This opens the possibility to adjust to multiple changes only once.

Example: Executed steps within UIBoxLayout:

  1. do_layout()
    1. Collect current size, size_hint, size_hint_min of children

    2. Calculate the new position and sizes

    3. Set position and size of children

  2. Recursively call do_layout on child layouts (last step in do_layout())

┌─────────┐          ┌────────┐                      ┌────────┐
│UIManager│          │UILayout│                      │children│
└────┬────┘          └───┬────┘                      └───┬────┘
     │   do_layout()    ┌┴┐                              │
     │─────────────────>│ │                              │
     │                  │ │                              │
     │                  │ │                              │
     │     ╔════════════╪═╪════╤═════════════════════════╪══════════════╗
     │     ║ place children    │                         │              ║
     │     ╟────────────────use size, size_hint, ...     │              ║
     │     ║            │ │ <─────────────────────────────              ║
     │     ║            │ │                              │              ║
     │     ║            │ │       set size and pos       │              ║
     │     ║            │ │ ─────────────────────────────>              ║
     │     ╚════════════╪═╪══════════════════════════════╪══════════════╝
     │                  │ │                              │
     │                  │ │                              │
     │     ╔═══════╤════╪═╪══════════════════════════════╪══════════════╗
     │     ║ LOOP  │  sub layouts                        │              ║
     │     ╟───────┘    │ │                              │              ║
     │     ║            │ │          do_layout()         │              ║
     │     ║            │ │ ─────────────────────────────>              ║
     │     ╚════════════╪═╪══════════════════════════════╪══════════════╝
     │                  └┬┘                              │
     │                   │                               │
     │<─ ─ ─ ─ ─ ─ ─ ─ ─ │                               │
┌────┴────┐          ┌───┴────┐                      ┌───┴────┐
│UIManager│          │UILayout│                      │children│
└─────────┘          └────────┘                      └────────┘

Size hint support#

size_hint

size_hint_min

size_hint_max

UIAnchorLayout

X

X

X

UIBoxLayout

X

X

X

UIGridLayout

X

X

X

UIManager

X

X

UIMixin#

Mixin classes are a base class which can be used to apply some specific behaviour. Currently the available Mixins are still under heavy development.

Constructs#

Constructs are predefined structures of widgets and layouts like a message box or (not yet available) file dialogues.

Available Elements#

Buttons#

As with most widgets, buttons take x, y, width, and height parameters for their sizing. Buttons specifically have two more parameters - text and multiline.

All button types support styling. And they are text widgets, which means you can use the _label attribute to get the label component of the button.

Flat button#

Name: FlatButton

A flat button for simple interactions (hover, press, release, click). This button is created with a simple rectangle. Flat buttons can quickly create a nice-looking button. However, depending on your use case, you may want to use a texture button to further customize your look and feel.

Styling options are shown in the table below.

Name

Description

font_size

Font size for the button text. Defaults to 12.

font_name

Font name or family for the button text. If a tuple is supplied then arcade will attempt to load all of the fonts, prioritizing the first one. Defaults to ("calibri", "arial").

font_color

Font color for the button text (foreground). Defaults to white for normal, hover, and disabled states. Defaults to black for pressed state.

bg

Background color of the button. This modifies the color of the rectangle within the button and not the border. Instead of making each of these different colors for each of your buttons, set these towards a common color theme. Defaults to gray for hover and disabled states. Otherwise it is white.

border

Border color. It is common to only modify this in a focus or hover state. Defaults to white or turquoise for hover.

border_width

Width of the border/outline of the button. It is common to make this thicker on a hover or focus state, however an overly thick border will result in your GUI looking old or low-quality. Defaults to 2.

Image/texture button#

Name: UITextureButton

An image button. Textures are supplied from arcade.load_texture() for simple interactions (hover, press, release, click). A texture lets you further customize the look of the widget better than styling.

A texture button a few more arguments than a flat button. texture, texture_hovered, and texture_pressed will change the texture displayed on the button respectively. scale will change the scaling or size of the button - it’s similar to the sprite scale.

Hint

This widget does have width and height parameters, but they only stretch the texture instead of resizing it with keeping the borders. This feature is currently in-progress.

Texture buttons have fewer styling options when they have a texture compared to flat buttons.

Name

Description

font_size

Font size for the button text. Defaults to 12.

font_name

Font name or family for the button text. If a tuple is supplied then arcade will attempt to load all of the fonts, prioritizing the first one. Defaults to ("calibri", "arial").

font_color

Font color for the button text (foreground). Defaults to white for normal, hover, and disabled states. Defaults to black for pressed state.

border_width

Width of the border/outline of the button. It is common to make this thicker on a hover or focus state, however an overly thick border will result in your GUI looking old or low-quality. Defaults to 2.

Text widgets#

All text widgets take x and y positioning parameters. They also accept text and multiline options.

Label#

Name: UILabel

A label is used to display text as instruction for the user. Multiline text is supported, and what would have been its style options were moved into the parameters.

This widget has no style options whatsoever, and they have been moved into the parameters. bold and italic will set the text to bold or italic. align specifies the justification of the text. Additionally it takes font_name, font_size, and text_color options.

Using the label property accesses the internal Text class.

Hint

A text attribute can modify the displayed text. Beware-calling this again and again will give a lot of lag. Use begin_update() and py:meth:~arcade.Text.end_update to speed things up.

Text input field#

Name: UIInputText

A text field allows a user to input a basic string. It uses pyglet’s IncrementalTextLayout and its Caret. These are stored in layout and caret properties.

This widget takes width and height properties and uses a rectangle to display a background behind the layout.

A text input field allows the user to move a caret around text to modify it, as well as selecting parts of text to replace or delete it. Motion symbols for a text field are listed in pyglet.window.key module.

Text area#

Name: UITextArea

A text area is a scrollable text widget. A user can scroll the mouse to view a rendered text document. This does not support editing text. Think of it as a scrollable label instead of a text field.

width and height allocate a size for the text area. If text does not fit within these dimensions then only part of it will be displayed. Scrolling the mouse will display other sections of the text incrementally. Other parameters include multiline and scroll_speed. See view_y on scroll speed.

Use layout and doc to get the pyglet layout and document for the text area, respectively.

User-interface events#

Arcade’s GUI events are fully typed dataclasses, which provide information about an event affecting the UI.

All pyglet window events are converted by the UIManager into UIEvents and passed via dispatch_event() to the on_event() callbacks.

Widget-specific events (such as UIOnClickEvent are dispatched via on_event and are then dispatched as specific event types (like on_click).

A full list of event attributes is shown below.

Event

Attributes

UIEvent

None

UIMouseEvent

x, y

UIMouseMovementEvent

dx, dy

UIMousePressEvent

dx, dy, button, modifiers

UIMouseDragEvent

dx, dy

UIMouseScrollEvent

scroll_x, scroll_y

UIKeyEvent

symbol, modifiers

UIKeyReleaseEvent

None

UITextEvent

text

UITextMotionEvent

motion

UITextMotionSelectEvent

selection

UIOnClickEvent

None

UIOnUpdateEvent

dt

UIOnChangeEvent

old_value, new_value

UIOnActionEvent

action

  • arcade.gui.UIEvent. Base class for all events.

  • arcade.gui.UIMouseEvent. Base class for mouse-related events.
  • UITextEvent. Text input from user. This is only used for text fields and is the text as a string that was inputed.

  • UITextMotionEvent. Text motion events. This includes moving the text around with the caret. Examples include using the arrow keys, backspace, delete, or any of the home/end and PgUp/PgDn keys. Holding Control with an arrow key shifts the caret by a entire word or paragraph. Moving the caret via the mouse does not trigger this event.

  • UITextMotionSelectEvent. Text motion events for selection. Holding down the Shift key and pressing arrow keys (Control optional) will select character(s). Additionally, using a Control-A keyboard combination will select all text. Selecting text via the mouse does not trigger this event.

  • UIOnUpdateEvent. This is a callback to the arcade on_update method.

Widget-specific events#

Widget events are only dispatched as a pyglet event on a widget itself and are not passed through the widget tree.

Different event systems#

Arcade’s GUI uses different event systems, dependent on the required flow. A game developer should mostly interact with user-interface events, which are dispatched from specific UIWidget`s like an ``on_click` of a button.

In rare cases a developer might implement some widgets themselves or want to modify the existing GUI behavior. In those cases a developer might register own pyglet event types on widgets or overwrite the on_event method. In that case, refer to existing widgets as an example.

Pyglet window events#

Pyglet window events are received by UIManager.

You can dispatch them via:

UIWidget.dispatch_event("on_event", UIEvent(...))

Window events are wrapped into subclasses of UIEvent.

Pyglet event dispatcher - UIWidget#

Widgets implement pyglet’s EventDispatcher and register an on_event event type.

on_event() contains specific event handling and should not be overwritten without deeper understanding of the consequences.

To add custom event handling, use the decorator syntax to add another listener:

@UIWidget.event("on_event")

User-interface events#

User-interface events are typed representations of events that are passed within the GUI. Widgets might define and dispatch their own subclasses of these events.

Property#

Property is an pure-Python implementation of Kivy Properties. They are used to detect attribute changes of widgets and trigger rendering. They should only be used in arcade internal code.