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.
Controles GUI personalizados¶
Tantos controles...¶
Sin embargo, nunca hay suficientes. Crear tus propios controles personalizados que actúen como tú quieres es una obsesión de casi todos los programadores de GUI. Godot proporciona muchos de ellos, pero puede que no funcionen exactamente de la manera que quieres. Antes de contactar a los desarrolladores con una solicitud de soporte para barras de desplazamiento diagonales, al menos será bueno saber cómo crear estos controles fácilmente desde el script.
Dibujando¶
Para dibujar, se recomienda consultar el tutorial Dibujos personalizados en 2D. Lo mismo se aplica. Algunas funciones son dignas de mención por su utilidad a la hora de dibujar, por lo que se detallarán a continuación:
Comprobando el tamaño del control¶
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.
Comprobando el enfoque¶
Algunos controles (como los botones o los editores de texto) pueden proporcionar un enfoque de entrada para el teclado o el joypad de entrada. Ejemplos de ello son la introducción de texto o la pulsación de un botón. Esto se controla con la propiedad Control.focus_mode. Cuando se dibuja, y si el control soporta el enfoque de entrada, siempre se desea mostrar algún tipo de indicador (resaltado, cuadro, etc.) para indicar que este es el control actualmente enfocado. Para comprobar este estado, existe el método Control.has_focus(). Ejemplo
func _draw():
if has_focus():
draw_selected()
else:
draw_normal()
public override void _Draw()
{
if (HasFocus())
{
DrawSelected()
}
else
{
DrawNormal();
}
}
Escalando¶
Como se mencionó anteriormente, el tamaño es importante para los Control. Esto les permite colocarse correctamente, cuando se colocan en rejillas, contenedores o cuando están anclados. La mayoría de las veces, proporcionan un tamaño mínimo para ayudar a colocarlos correctamente. Por ejemplo, se colocan verticalmente uno encima del otro usando un VBoxContainer, el tamaño mínimo se asegurará de que su control personalizado no sea aplastado por los otros controles en el contenedor.
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);
}
Alternativamente, configúralo usando una función:
func _ready():
set_custom_minimum_size(Vector2(30, 30))
public override void _Ready()
{
SetCustomMinimumSize(new Vector2(20, 20));
}
Entrada¶
Los controles proporcionan unos cuantos ayudantes para que la gestión de los eventos de entrada sea mucho más fácil que la de los nodos regulares.
Eventos de entrada¶
Hay algunos tutoriales sobre la entrada de datos antes de este, pero vale la pena mencionar que los controles tienen un método especial de entrada de datos que sólo funciona cuando:
El puntero del mouse está sobre el control.
El botón fue presionado sobre este control (el control siempre captura la entrada hasta que se suelta el botón)
Control proporciona el foco del teclado/joypad a través de 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!")
public override void _GuiInput(InputEvent @event)
{
if (@event is InputEventMouseButton mbe && mbe.ButtonIndex == MouseButton.Left && mbe.Pressed)
{
GD.Print("Left mouse button was pressed!");
}
}
Para obtener más información sobre los eventos propios, consulte el tutorial Usando InputEvent.
Notificaciones¶
Los nodos Control también tienen muchas notificaciones útiles para los que no existe ninguna llamada de retorno, pero que se pueden verificar con la llamada de retorno _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;
}
}