NumberField

NumberField is a text field for an int or a double with an optional range, built-in errors for bad input and an optional extra validator.

Last updated

On this page

A TextInput for a number, optionally between a minimum and a maximum. Use it where the player types an exact number (a port, a seed, a radius); for a value the player drags, use a Slider.

NumberField.ofInt("radius")
        .label(Text.translatable("mymod.radius", "Radius (blocks)"))
        .initial(config.radius)
        .range(1, 256)
        .onChange(r -> config.radius = r)
        .build();

NumberField.ofDouble("scale")
        .label(Text.translatable("mymod.scale", "Scale"))
        .initial(config.scale)
        .range(0.1, null)                       // no upper bound
        .onChange(s -> config.scale = s)
        .build();

Builder#

Start with NumberField.ofInt(id) (whole numbers, Integer) or NumberField.ofDouble(id) (Double).

Method Required Default Notes
label(Supplier<Text>) / label(Text) yes the text above the field
initial(N) yes the starting number, usually your current value. Shown without trailing zeros; not checked against the range or passed to onChange.
onChange(Consumer<? super N>) yes receives the number after each edit that leaves the text valid; main thread
range(N min, N max) no unbounded (ofInt: the int range) both inclusive; either may be null for no bound
maxLength(int) no 32 the most characters the field accepts
validator(Function<? super N, Text>) no none an extra check; returns an error or null. Runs last, only on in-range numbers.
enabled, tooltip, visible no options every widget has

build() throws if a required field is missing, a number is NaN or infinite, min > max, or maxLength isn't positive.

Built-in errors#

Input Error below the field
empty, or not a number Not a number
a decimal in an ofInt field (2.5; 2.0 counts as 2) Not a whole number
below the minimum Must be at least min
above the maximum Must be at most max

The text is trimmed and parsed with . as the decimal separator in every language; 1e3 is accepted.

Methods#

Method Gives
number() the number in the field, for an action that reads it directly
input() the TextInput it is drawn as: input().value() is the text, input().isValid() whether it's valid
min(), max() the bounds, or null

Behaviour#

Test it#

host.type("radius", "300");
assertTrue(host.render().contains("(error: Must be at most 256)"));

Rendered as [input radius] Radius (blocks): "300" (error: Must be at most 256).

See also#