Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

How to receive a result from a screen

Purpose. You open a screen for the user to choose/fill in something and need the value back. CrossFly has two distinct mechanisms: show(onAnswer) for pickers, and a constructor callback for regular screens.

APIs used

  • Window.show(RunnableWith<Object> onAnswer) — registers a result callback. In the source, the callback only fires if getAnswer() != null, and Window.getAnswer() returns null by default — only Picker overrides getAnswer(). In other words: for regular screens this callback never fires.
  • Picker.getAnswer() — returns the chosen value, or null if cancelled. Only pickers implement it.
  • Constructor callback — the pattern for regular screens: pass a RunnableWith<T> (or your own interface) to the screen’s constructor and invoke it before hide().

Complete example (copy, paste, and run)

package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Runnable main screen: opens the selection screen and receives the result via a callback in the constructor. */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      add(new Label("Nenhum cliente escolhido"));
      add(new Button("Escolher cliente").onAction(e ->
         // COMMON SCREEN — result via callback in the constructor (show(onAnswer) does NOT work here).
         new SelecionarClienteTela(cliente -> Hint.show("Escolhido: " + cliente.nome, 1500)).show()));
   }
}

/** Simple example model. */
class Cliente
{
   final String nome;
   Cliente(String nome) { this.nome = nome; }
}

/** Selection screen: delivers the result through the constructor callback before closing. */
class SelecionarClienteTela extends Window
{
   private final RunnableWith<Cliente> onPick;

   public SelecionarClienteTela(RunnableWith<Cliente> onPick) { this.onPick = onPick; }

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());
      add(new Button("Escolher Ana").onAction(e ->
      {
         if (onPick != null) onPick.run(new Cliente("Ana"));  // delivers the result
         hide();                                              // then closes
      }));
   }
}

The snippet below shows only the core. To run it, place it in the MainWindow skeleton above.

Minimal snippet

// verified in the source: hide() only calls onAnswer.run(answer) when (this instanceof Picker) and answer != null

// 1) PICKER — uses show(onAnswer). Fires ONLY with a non-null result (confirmed choice).
DatePicker picker = new DatePicker(/* ... */);
picker.show(answer ->
{
   Date d = (Date) answer;      // never null here; cancelling does NOT fire the callback
   Hint.show("Data: " + d, 1500);
});

// 2) COMMON SCREEN — result via callback in the constructor (show(onAnswer) does NOT work here).
public class SelecionarClienteTela extends Window
{
   private final RunnableWith<Cliente> onPick;

   public SelecionarClienteTela(RunnableWith<Cliente> onPick) { this.onPick = onPick; }

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new GridLayout());
      add(new Button("Escolher Ana").onAction(e ->
      {
         if (onPick != null) onPick.run(new Cliente("Ana"));  // delivers the result
         hide();                                              // then closes
      }));
   }
}

// call:
new SelecionarClienteTela(cliente -> Hint.show("Escolhido: " + cliente.nome, 1500)).show();

Why two paths? hide() calls onAnswer only for Picker (the instanceof Picker check is in the Window.hide() code). For regular screens, the constructor callback is the explicit contract — and it lets you type the result (RunnableWith<Cliente>) instead of Object.

Go deeper

Was this page helpful?