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 aUILayout
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
:
do_layout()
Collect current
size
,size_hint
,size_hint_min
of childrenCalculate the new position and sizes
Set position and size of children
Recursively call
do_layout
on child layouts (last step indo_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 |
|
---|---|---|---|
|
X |
X |
X |
|
X |
X |
X |
|
X |
X |
X |
|
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#
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 |
---|---|
|
None |
|
|
|
|
|
|
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
arcade.gui.UIEvent
. Base class for all events.arcade.gui.UIMouseEvent
. Base class for mouse-related events.arcade.gui.UIMouseMovementEvent
. Mouse motion. This event has an additionalpos
property that returns a tuple of the x and y coordinates.UIMousePressEvent
. Mouse button pressed.UIMouseDragEvent
. Mouse pressed and moved (drag).UIMouseReleaseEvent
. Mouse button release.UIMouseScrollEvent
. Mouse scroll.
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. HoldingControl
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 theShift
key and pressing arrow keys (Control
optional) will select character(s). Additionally, using aControl-A
keyboard combination will select all text. Selecting text via the mouse does not trigger this event.UIOnUpdateEvent
. This is a callback to the arcadeon_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.
UIOnClickEvent
. Click event ofUIInteractiveWidget
class. This is triggered on widget press.UIOnChangeEvent
. A value of aUIWidget
has changed.UIOnActionEvent
. An action results from interaction with theUIWidget
(mostly used in constructs)
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.