Retornar valores de uma tela
Há dois padrões, e escolher o certo evita um bug comum.
⚠️ Ponto crítico
O Window.show(onAnswer) só dispara o onAnswer se a janela for um Picker (internamente,
hide() faz answer = this instanceof Picker ? getAnswer() : null e só chama o callback se
answer != null). Para uma tela comum (subclasse de Window), show(onAnswer) não retorna
valor — use o padrão de callback pelo construtor.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;
import dev.crossfly.util.*; // RunnableWith
/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
Label resultado = new Label("Nenhuma escolha ainda");
add(LAY_AUTO, resultado);
Button escolher = new Button("Escolher opção");
// Tela comum → callback PELO CONSTRUTOR (show(cb) só dispara em Picker).
escolher.onAction(c ->
new TelaSelecao(op -> resultado.setText("Escolheu: " + op)).show());
add(LAY_AUTO, escolher);
}
}
/** Tela comum que devolve um valor pelo callback recebido no construtor. */
class TelaSelecao extends Window
{
private final RunnableWith<String> onEscolha;
public TelaSelecao(RunnableWith<String> onEscolha) { this.onEscolha = onEscolha; }
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
Button a = new Button("Opção A");
a.onAction(c -> { onEscolha.run("A"); hide(); }); // devolve e fecha
add(LAY_AUTO, a);
Button b = new Button("Opção B");
b.onAction(c -> { onEscolha.run("B"); hide(); });
add(LAY_AUTO, b);
}
}
Os trechos abaixo mostram só o miolo (o que vai dentro de
onShow()). Para rodar, coloque-os no esqueletoMainWindowacima.
Padrão 1 — callback pelo construtor (telas comuns)
Passe um callback ao construtor da tela; ela o invoca antes de hide():
public class TelaSelecao extends Window {
private final RunnableWith<String> onEscolha;
public TelaSelecao(RunnableWith<String> onEscolha) { this.onEscolha = onEscolha; }
@Override public void onShow() throws Exception {
super.onShow();
setLayout(new VerticalLayout());
Button opa = new Button("Opção A");
opa.onAction(c -> { onEscolha.run("A"); hide(); }); // devolve e fecha
add(LAY_AUTO, opa);
}
}
// uso:
new TelaSelecao(resultado -> System.out.println("Escolheu: " + resultado)).show();
Padrão 2 — Picker + onAnswer (seletores prontos)
Os pickers (DatePicker, TimePicker, ColorPicker, etc.) já implementam
getAnswer(). Para eles, use show(onAnswer):
new DatePicker().show(resposta -> {
// só dispara se != null (usuário confirmou; cancelar ⇒ getAnswer() nulo)
System.out.println("Data: " + resposta);
});
Para criar seu próprio seletor, estenda Picker e implemente getAnswer().
⚠️ Diálogos NÃO usam onAnswer
Alert e ActionSheet estendem Window (não Picker), então show(callback) não dispara. A
resposta vem pelos callbacks dos botões (buttonAction) — ver Diálogos e modais.
Boas práticas
- Telas comuns → callback no construtor. Seletores →
Picker+onAnswer. - Para estado compartilhado entre telas, considere um ViewModel/controller (ver arquitetura).
Erros comuns
- Usar
minhaTela.show(cb)esperando ocbdisparar numa tela que não éPicker(não dispara). - Usar
alert.show(cb)— o callback nunca roda; usebuttonAction.