Benutzerdefinierte GUI-Steuerelemente

So viele Kontrollen ...

Doch es gibt nie genug. Das Erstellen eigener benutzerdefinierter Steuerelemente, die genau so funktionieren, wie Sie es möchten, ist eine Besessenheit fast aller GUI-Programmierer. Godot bietet viele davon, aber sie funktionieren möglicherweise nicht genau so, wie Sie es möchten. Bevor Sie sich mit einer Pull-Anfrage an die Entwickler wenden, um diagonale Bildlaufleisten zu unterstützen, sollten Sie zumindest wissen, wie Sie diese Steuerelemente einfach aus dem Skript erstellen können.

Zeichnen

Zum Zeichnen wird empfohlen, die Anleitung Benutzerdefinierte Zeichnung in 2D zu lesen. Einige Funktionen sind aufgrund ihrer Nützlichkeit beim Zeichnen erwähnenswert, daher werden sie als nächstes detailliert beschrieben:

Kontrollgröße prüfen

Im Gegensatz zu 2D-Nodes ist "Größe" bei Steuerelementen wichtig, um das Layouts organisiert zu können. Hierzu wird die Eigenschaft Control.rect_size bereitgestellt. Sie zu überprüfen während _draw() ist wichtig, um sicherzustellen, dass alle Grenzen eingehalten wird.

Fokus prüfen

Einige Steuerelemente (z.B. Schaltflächen oder Texteditoren) bieten möglicherweise einen Eingabefokus für die Tastatur- oder Joypad-Eingabe. Beispiele hierfür sind die Eingabe von Text oder das Drücken einer Taste. Dies wird mit der Eigenschaft Control.focus_mode gesteuert. Beim Zeichnen (wenn das Steuerelement den Eingabefokus unterstützt) ist es immer wünschenswert eine Art Indikator (Hervorhebung, Feld usw.) anzuzeigen, um das aktuell fokussierte Steuerelement zu erkennen. Um diesen Status zu überprüfen, ist die Methode Control.has_focus() vorhanden. Beispiel:

func _draw():
    if has_focus():
         draw_selected()
    else:
         draw_normal()
public override void _Draw()
{
    if (HasFocus())
    {
        DrawSelected()
    }
    else
    {
        DrawNormal();
    }
}

Dimensionierung

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)
public override Vector2 _GetMinimumSize()
{
    return new Vector2(20, 20);
}

Alternativ können Sie es mit einer Funktion einstellen:

func _ready():
    set_custom_minimum_size(Vector2(30, 30))
public override void _Ready()
{
    SetCustomMinimumSize(new Vector2(20, 20));
}

Eingang

Steuerelemente bieten einige Hilfsmittel, um die Verwaltung von Eingabeereignissen viel einfacher zu gestalten als bei normalen Nodes.

Eingabe-Events

Vor diesem gibt es einige Anleitungen zur Eingabe, aber es ist erwähnenswert, dass Steuerelemente eine spezielle Eingabemethode haben, die nur funktioniert, wenn:

  • Der Mauszeiger sich über dem Steuerelement befindet.
  • Die Taste über diese Steuerung gedrückt wurde (die Steuerung erfasst immer die Eingabe, bis die Taste losgelassen wird)
  • 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 == BUTTON_LEFT and event.pressed:
       print("Left mouse button was pressed!")
public override void _GuiInput(InputEvent @event)
{
    if (@event is InputEventMouseButton mbe && mbe.ButtonIndex == (int)ButtonList.Left && mbe.Pressed)
    {
        GD.Print("Left mouse button was pressed!");
    }
}

Für mehr Informationen über Events, siehe Eingabe-Ereignisse Anleitung.

Benachrichtigungen

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.
public override void _Notification(int what)
{
    switch (what)
    {
        case NotificationMouseEnter:
            // Mouse entered the area of this control.
            break;

        case NotificationMouseExit:
            // Mouse exited the area of this control.
            break;

        case NotificationFocusEnter:
            // Control gained focus.
            break;

        case NotificationFocusExit:
            // Control lost focus.
            break;

        case NotificationThemeChanged:
            // Theme used to draw the control changed;
            // update and redraw is recommended if using a theme.
            break;

        case NotificationVisibilityChanged:
            // Control became visible/invisible;
            // check new status with is_visible().
            break;

        case NotificationResized:
            // Control changed size; check new size with get_size().
            break;

        case NotificationModalClose:
            // For modal pop-ups, notification that the pop-up was closed.
            break;
    }
}