Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar

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 esqueleto MainWindow acima.

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 o cb disparar numa tela que não é Picker (não dispara).
  • Usar alert.show(cb) — o callback nunca roda; use buttonAction.

Veja também

Esta página foi útil?