This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
Focus and validation
Since there is no per-key event, validation in CrossFly happens on submit (or when focus is
lost): you read getText(), decide, and flag the error.
Complete example (copy, paste and run)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*; // TextFieldStyle (behavioral config)
/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
TextField nome = new TextField().caption("Nome");
add(LAY_AUTO, nome);
TextField email = new TextField().caption("E-mail");
add(LAY_AUTO, email);
// Read-only field: shows value, does not open keyboard or focus on tap
TextField codigo = new TextField("ABC-123").caption("Código");
codigo.<TextFieldStyle>getStyle().editable(false);
add(LAY_AUTO, codigo);
// Validation HAPPENS ON SUBMIT (there is no per-key event):
// empty field → Hint.show(...) + returns focus to the field with the error.
Button enviar = new Button("Cadastrar");
enviar.onAction(c -> {
String n = nome.getText().trim();
String e = email.getText().trim();
if (n.isEmpty()) { Hint.show("Informe o nome", 2000); nome.setFocused(true); return; }
if (e.indexOf('@') < 0) { Hint.show("E-mail inválido", 2000); email.setFocused(true); return; }
Hint.show("Cadastrado: " + n, 2000);
});
add(LAY_AUTO, enviar);
}
}
The snippets below show only the core (what goes inside
onShow()). To run them, place them in theMainWindowskeleton above.
Focus
| Property (style) / method | Effect |
|---|---|
focusOnTouch (style) |
touching the field gives it focus (default in field styles) |
focusOnKey (style) |
typing with the parent focused moves focus to the field |
onFocus() / onBlur() |
hooks called on gaining / losing focus (override in a subclass) |
hasFocus() |
queries whether the field is focused |
restoreFocusAtEnd() |
repositions the cursor at the end (after filling via a picker) |
// read-only field (shows value, does not open keyboard or focus on tap):
saldo.<TextFieldStyle>getStyle().editable(false);
Input limits
telefone.<TextFieldStyle>getStyle()
.maxLength(11) // at most 11 characters
.capitalise(Capitalise.UPPER); // forces uppercase (Capitalise: NORMAL/UPPER/LOWER)
Validate on submit (recommended pattern)
Button enviar = new Button("Cadastrar");
enviar.onAction(c -> {
String nome = nomeField.getText().trim();
String email = emailField.getText().trim();
if (nome.isEmpty()) { Hint.show("Informe o nome", 2000); nomeField.setFocused(true); return; }
if (email.indexOf('@') < 0) { Hint.show("E-mail inválido", 2000); emailField.setFocused(true); return; }
salvar(nome, email);
});
Hint.show(...)for non-blocking notices;Alertfor confirmations (see Dialogs and modals).- Return focus to the field with the error so the user can correct it.
Best practices
- Validate at submit time reading
getText()/getTextWithoutMask()— don’t try to intercept every key. - Use
editable(false)for calculated/derived fields instead of “disabling and forcing read-only”. - Restrict input at the source (
mask,maxLength,EditMode.NUMERIC) to reduce validation.
Common mistakes
- Looking for a per-key change listener — it doesn’t exist; validate on submit/on leaving the field.
- Forgetting to return focus to the invalid field, leaving the user lost.
- Validating
getText()(with mask) when the rule is about the digits → usegetTextWithoutMask().
See also
Was this page helpful?Thanks for the feedback!