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.

Picker (base class)

Picker is the common base of all CrossFly selection windows (date, time, file, photo, color, barcode, coordinate). Each picker opens, lets the user interact and, upon confirming, closes itself, delivering the result asynchronously, via callback, to the code that opened it.

Understanding the pattern on this page means understanding all pickers at once.

🟡 · Package: dev.crossfly.ui.picker · Extends: Window · Transition: FADE by default

The central pattern: getAnswer() + show(onAnswer)

  • Picker.getAnswer() produces the selected value (each subclass overrides it to return the concrete type: String, Integer, LatLon…). In the base, it returns null.
  • Window.show(RunnableWith<Object> onAnswer) consumes that value when the window is closed.

The link between the two lies in Window.hide():

public void hide() {
   ...
   Object answer = this instanceof Picker ? ((Picker) this).getAnswer() : null;
   if (onAnswer != null && answer != null)
      onAnswer.run(answer);
   ...
}

Practical consequences (all confirmed in the code):

  • The onAnswer callback only fires in hide() and only if getAnswer() != null. When canceling, subclasses make getAnswer() return null — so onAnswer is not called. Anyone who needs to react to the cancellation must override onHide()/onRemove() or use the subclass-specific callback.
  • show(onAnswer) is thread-safe: if called outside the paint thread, it is rescheduled and blocks until completed.
  • The delivered value is Object; the consumer casts it to the picker’s concrete type.

This contrasts with Alert/ActionSheet, which extend Window but not Picker — in them show(onAnswer) does not fire and the response comes via button callbacks.

Complete example (copy, paste and run)

package com.exemplo;

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

/** 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());

      Button abrir = new Button("Abrir picker");
      abrir.onAction(c ->
      {
         // Any Picker subclass follows the same show(onAnswer) pattern
         DatePicker dp = new DatePicker();
         dp.show(answer ->
         {
            // 'answer' is the Object returned by getAnswer(); only reaches here if != null
            String data = (String) answer;
            Hint.show("Selecionado: " + data, 2000);
         });
      });
      add(LAY_AUTO, abrir);
   }
}

The snippets below show only the core (what goes inside onShow()). To run them, place them in the MainWindow skeleton above.

Basic usage (generic form of any picker)

DatePicker dp = new DatePicker();
dp.show(answer ->
{
   // 'answer' is the Object returned by getAnswer(); only reaches here if != null
   String data = (String) answer;
   Debug.log("Selecionado: " + data);
});

Public methods

Method Return Description
getAnswer() Object Picker result, or null if canceled. Overridden by each subclass.
show(RunnableWith<Object> onAnswer) void Opens the picker; delivers the value via callback on close (inherited from Window).

Types returned by subclass

Picker getAnswer() returns
DatePicker String (date per LocaleFormats.dateFormat/dateSeparator)
TimePicker String (HH:MM, 24h)
FilePicker — (empty skeleton; inherits null from the base)
PhotoPicker String (path or "ERROR: ...")
ColorPicker Integer (RGB without alpha)
BarcodePicker String (payload read)
LocationPicker LatLon

Best practices

  • Always cast the Object to the concrete type from the table above.
  • To react to cancellation, do not rely on onAnswer — use the specific callback (onSelect/onCapture) or override onHide().
  • Hardware pickers (PhotoPicker, BarcodePicker, LocationPicker) release resources on close; do not reuse the same instance after hide().

Common mistakes

  • Expecting onAnswer on cancellation — it does not fire, because getAnswer() returns null.
  • Forgetting the cast — the callback receives Object.

See also

Was this page helpful?