定制 GUI 的Control节点

已经有好多control节点了...

然而, 这远远不够. 创建您的自定义控件, 并使其按您希望的方式工作, 这几乎是每个GUI程序员都向往的事情.Godot提供了大量这样的工具, 但它们可能并不完全如您所愿的方式工作. 在使用支持对角滚动条的下拉请求与开发人员联系之前, 至少应该了解如何从脚本轻松地创建这些控件.

绘制

谈到绘制, 推荐看看这篇 2D中的自定义绘图 的教程. 同样的原理适用与控件绘制. 这里有些函数值得一提, 因为它们在绘制时有用, 所以接下来将进行详细说明:

检查控件的大小

与2D节点不同,"size" 对控件很重要, 因为它有助于在适当的布局中组织它们. 为此, 我们提供了 Control.rect_size 属性. 在 _draw() 中检查它以确保所有东西都在范围之内.

检查输入焦点

一些控件(如按钮或文本编辑器)可为键盘或手柄输入提供输入焦点. 这方面的例子是输入文本或按下一个按钮. 这可以通过 Control.focus_mode 属性来控制. 绘制时, 如果控件支持输入焦点, 总是希望显示某种指示来表明(高亮, 方框等), 当前这是焦点控件. 为了检查这个状态, 存在一个 Control.has_focus() 的方法. 例子

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

调整大小

如前所述, 尺寸对控件是很重要的. 这可以让它们在设置网格, 容器或锚定时以正确布局. 控件, 在大多数情况下, 提供了一个 minimum size , 以帮助它们正确布局. 例如, 如果控件被垂直放置在彼此的顶部, 使用 VBoxContainer , 最小尺寸将确保你的自定义控件不会被容器中的其他控件挤压.

要提供此回调, 只需重写 Control.get_minimum_size() , 例如:

func get_minimum_size():
    return Vector2(30, 30)
public override Vector2 _GetMinimumSize()
{
    return new Vector2(20, 20);
}

或者, 使用函数进行设置:

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

输入

控件(Control)节点提供了一些帮助, 使管理输入事件比常规节点容易得多.

输入事件

在此之前有几个关于输入的教程, 但值得一提的是, 控件有一个特殊的输入方法, 只有在以下情况下才起作用:

  • 鼠标指针悬停在控件上.

  • 鼠标按键在此控件上被按下 (控件始终捕获输入, 直到按钮被释放)

  • 控件通过以下方式提供键盘和手柄焦点 Control.focus_mode.

这个函数 Control._gui_input() . 只需在你的控件中重写它. 不需要设置处理.

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!");
    }
}

有关事件(event)本身的详细信息, 请查看 使用输入事件InputEvent 教程.

通知

控件也有许多有用的通知, 这些通知不存在专门的回调, 但可以用_notification回调来检查:

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;
    }
}