Work in progress

The content of this page was not yet updated for Godot 4.2 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

Custom GUI controls

Так много элементов управления...

Yet there are never enough. Creating your own custom controls that act just the way you want them to is an obsession of almost every GUI programmer. Godot provides plenty of them, but they may not work exactly the way you want. Before contacting the developers with a pull-request to support diagonal scrollbars, at least it will be good to know how to create these controls easily from script.

Отрисовка

For drawing, it is recommended to check the Пользовательская отрисовка в 2D tutorial. The same applies. Some functions are worth mentioning due to their usefulness when drawing, so they will be detailed next:

Checking control size

Unlike 2D nodes, "size" is important with controls, as it helps to organize them in proper layouts. For this, the Control.size property is provided. Checking it during _draw() is vital to ensure everything is kept in-bounds.

Проверка фокуса

Некоторые элементы управления (например, кнопки или текстовые редакторы) могут предоставлять фокус ввода для ввода с клавиатуры или джойпада. Примерами этого являются ввод текста или нажатие кнопки. Это контролируется с помощью свойства Control.focus_mode. При рисовании, если элемент управления поддерживает фокус ввода, всегда желательно показывать какой-либо индикатор (выделение, рамку и т.д.), чтобы указать, что это текущий сфокусированный элемент управления. Для проверки этого состояния существует метод Control.has_focus(). Пример

func _draw():
    if has_focus():
         draw_selected()
    else:
         draw_normal()

Определение размеров

As mentioned before, size is important to controls. This allows them to lay out properly, when set into grids, containers, or anchored. Controls, most of the time, provide a minimum size to help properly lay them out. For example, if controls are placed vertically on top of each other using a VBoxContainer, the minimum size will make sure your custom control is not squished by the other controls in the container.

To provide this callback, just override Control._get_minimum_size(), for example:

func _get_minimum_size():
    return Vector2(30, 30)

Alternatively, set it using a function:

func _ready():
    set_custom_minimum_size(Vector2(30, 30))

Вход

Controls provide a few helpers to make managing input events much easier than regular nodes.

Входящие события

There are a few tutorials about input before this one, but it's worth mentioning that controls have a special input method that only works when:

  • Указатель мыши находится над элементом управления.

  • Кнопка была нажата над этим элементом управления (элемент управления всегда фиксирует ввод до отпускания кнопки)

  • Control provides keyboard/joypad focus via Control.focus_mode.

This function is Control._gui_input(). Simply override it in your control. No processing needs to be set.

extends Control

func _gui_input(event):
   if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
       print("Left mouse button was pressed!")

Для получения дополнительной информации о самих событиях посмотрите руководство Использование InputEvent.

Уведомления

Controls also have many useful notifications for which no dedicated callback exists, but which can be checked with the _notification callback:

func _notification(what):
    match what:
        NOTIFICATION_MOUSE_ENTER:
            pass # Mouse entered the area of this control.
        NOTIFICATION_MOUSE_EXIT:
            pass # Mouse exited the area of this control.
        NOTIFICATION_FOCUS_ENTER:
            pass # Control gained focus.
        NOTIFICATION_FOCUS_EXIT:
            pass # Control lost focus.
        NOTIFICATION_THEME_CHANGED:
            pass # Theme used to draw the control changed;
            # update and redraw is recommended if using a theme.
        NOTIFICATION_VISIBILITY_CHANGED:
            pass # Control became visible/invisible;
            # check new status with is_visible().
        NOTIFICATION_RESIZED:
            pass # Control changed size; check new size
            # with get_size().
        NOTIFICATION_MODAL_CLOSE:
            pass # For modal pop-ups, notification
            # that the pop-up was closed.