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.

Masks and keyboards

The field’s EditMode controls two things at once: the formatting (mask) and the keyboard that opens. It is the central piece of structured input.

EditMode → keyboard

EditMode Formatting Keyboard that opens
NORMAL none OS default keyboard
NUMERIC digits native numeric (Keypad on desktop)
DATE date mask DatePicker
TIME time mask TimePicker
CURRENCY currency (separators) Keypad calculator
PASSWORD hides characters default keyboard

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

      // Date field: enabled mask opens the DatePicker on tap
      TextField data = new TextField().caption("Data");
      data.setMode(EditMode.DATE, true);      // maskedEdit=true → formats and opens DatePicker
      add(LAY_AUTO, data);

      // Currency field: formats as currency while typing
      TextField valor = new TextField().caption("Valor");
      valor.setMode(EditMode.CURRENCY, true);
      valor.<TextFieldStyle>getStyle().decimalPlaces(2);
      add(LAY_AUTO, valor);

      // Label where the read values will be displayed
      Label resultado = new Label("");
      add(LAY_AUTO, resultado);

      // There is NO per-key callback: read getText() on submit.
      // getTextWithoutMask() returns only the digits (good for saving to the database).
      Button enviar = new Button("Enviar");
      enviar.onAction(c -> resultado.setText(
         "Data = " + data.getText() + "  |  Valor = " + valor.getTextWithoutMask()));
      add(LAY_AUTO, enviar);
   }
}

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

Enable the automatic mask

setMode(mode, true) turns on real-time formatting (maskedEdit):

TextField data = new TextField().caption("Data");
data.setMode(EditMode.DATE, true);         // while typing, becomes 15/03/2024 and opens the DatePicker

TextField valor = new TextField().caption("Valor");
valor.setMode(EditMode.CURRENCY, true);    // formats as currency while typing
valor.<TextFieldStyle>getStyle().decimalPlaces(2);

Custom mask (the '9' is the digit)

In a mask, each '9' is a digit position; the other characters are fixed literals:

TextField cpf = new TextField().caption("CPF");
cpf.<TextFieldStyle>getStyle()
   .mask("999.999.999-99".toCharArray())    // 11 digits + separators
   .mode(EditMode.NUMERIC, true);
// getText()          -> "123.456.789-00"  (with mask)
// getTextWithoutMask()-> "12345678900"    (digits only)

Ready-made currency: TextField.getDefaultCurrencyMask(int casasDecimais) generates the mask with the locale’s thousands/decimal separators.

Choose the keyboard explicitly

campo.keyboard(Keyboard.NUMERIC);   // forces numeric
campo.keyboard(Keyboard.NONE);      // never opens keyboard (visually read-only field)

Keyboard (in UIConstants): NONE, DEFAULT, NUMERIC, KEYPAD, CALCULATOR, DATE, TIME. DEFAULT adopts the keyboard implied by the current EditMode.

Built-in Keypad

Keyboard.KEYPAD/CALCULATOR use CrossFly’s own Keypad component (not the OS keyboard) — useful in kiosks/POS. It is opened automatically by the field; to use it standalone:

new Keypad(meuCampo).show();        // numeric keyboard bound to the field

Best practices

  • Save the getTextWithoutMask() (raw digits) to the database; display it with the mask.
  • Combine mask(...) with mode(EditMode.NUMERIC, true) for documents (CPF, ZIP code, phone).
  • On desktop, NUMERIC falls back to the Keypad automatically — don’t assume a native keyboard.

Common mistakes

  • Turning on mode(EditMode.DATE) without maskedEdit=true → no automatic formatting.
  • Persisting getText() (with dots/dashes) when the back end expects only digits.
  • A mask with no '9' → no digit is accepted.

See also

Was this page helpful?