Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Controles de GUI personalizados
Muitos controles...
Ainda assim, nunca são suficientes. Criar seus próprios controles personalizados que agem exatamente da maneira que você deseja é uma obsessão de quase todo programador de GUI. O Godot fornece uma abundância deles, mas eles podem não funcionar exatamente como você deseja. Antes de entrar em contato com os desenvolvedores com um pull-request para dar suporte a barras de rolagem diagonais, pelo menos será bom saber como criar esses controles facilmente a partir de scripts.
Desenhando
Para desenhar, recomenda-se verificar o tutorial Desenho personalizado em 2D. O mesmo se aplica. Algumas funções valem a pena mencionar devido à sua utilidade ao desenhar, por isso serão detalhadas a seguir:
Verificando o tamanho do controle
Ao contrário dos nós 2D, o "tamanho" (size) é importante nos controles, pois ajuda a organizá-los em layouts adequados. Para isso, a propriedade Control.size é fornecida. Verificá-la durante o _draw() é vital para garantir que tudo seja mantido dentro dos limites.
Verificando o foco
Alguns controles (como botões ou editores de texto) podem fornecer foco de entrada para entrada de teclado ou controle (joypad). Exemplos disso são digitar texto ou pressionar um botão. Isso é controlado com la propriedade Control.focus_mode. Ao desenhar, e se o controle suportar foco de entrada, é sempre desejável mostrar algum tipo de indicador (destaque, caixa, etc.) para indicar que este é o controle focado no momento. Para verificar esse status, existe o método Control.has_focus(). Exemplo
func _draw():
if has_focus():
draw_selected()
else:
draw_normal()
public override void _Draw()
{
if (HasFocus())
{
DrawSelected()
}
else
{
DrawNormal();
}
}
Dimensionando
Como mencionado antes, o tamanho é importante para os controles. Isso permite que eles se organizem adequadamente quando inseridos em grades, containers ou ancorados. Os controles, na maioria das vezes, fornecem um tamanho mínimo para ajudar a organizá-los adequadamente. Por exemplo, se os controles forem colocados verticalmente uns sobre os outros usando um VBoxContainer, o tamanho mínimo garantirá que seu controle personalizado não seja esmagado pelos outros controles no container.
Para fornecer esse callback, basta sobrescrever o método Control._get_minimum_size(), por exemplo:
func _get_minimum_size():
return Vector2(30, 30)
public override Vector2 _GetMinimumSize()
{
return new Vector2(20, 20);
}
Como alternativa, defina-o usando uma função:
func _ready():
set_custom_minimum_size(Vector2(30, 30))
public override void _Ready()
{
CustomMinimumSize = new Vector2(20, 20);
}
Entrada
Os controles fornecem alguns assistentes para tornar o gerenciamento de eventos de entrada muito mais fácil do que nos nós regulares.
Eventos de entrada
Existem alguns tutoriais sobre entrada antes deste, mas vale a pena mencionar que os controles possuem um método de entrada especial que só funciona quando:
O ponteiro do mouse está sobre o controle.
O botão foi pressionado sobre este controle (o controle sempre captura a entrada até que o botão seja solto)
O controle fornece foco de teclado/controle via Control.focus_mode.
Esta função é o Control._gui_input(). Para usá-la, sobrescreva-a em seu controle. Nenhum processamento precisa ser configurado.
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!");
}
}
For more information about events themselves, see the Usando InputEvent tutorial.
Notificações
Controls also receive many useful notifications for which no dedicated virtual method
exists, but which can be checked within the _notification virtual method:
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().
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;
}
}