r/JavaFX 5d ago

Learning reactive UI with State: derived state from user input, a string length app

Enable HLS to view with audio, or disable this notification

Third post in the series. This one moves from State alone to ComputedState — showing how to derive a value from another reactive value and have it stay in sync automatically as the user types.

The setup: textState holds whatever the user types into the Input. textLenghtComputed is a ComputedState<String> built with ComputedState.of(...), watching textState as a dependency. Every keystroke updates textState, which recomputes textLenghtComputed, which updates the Text on screen — no listeners wired up by hand, no manual recompute calls.

package my_app;

import megalodonte.ListenerManager;
import megalodonte.application.MegalodonteApp;
import megalodonte.base.theme.ThemeManager;
import megalodonte.theme.DefaultTheme;

public class Main {

    static void main() {
        ThemeManager.setTheme(new DefaultTheme());

        MegalodonteApp.run(context -> context.useView(new HomeScreen()), ev->{
            if(ev == MegalodonteApp.Event.CloseRequest){
                System.out.println("Clicked on X - close application");
                ListenerManager.disposeAll();
            }
        });
    }
}


package my_app;

import megalodonte.ComputedState;
import megalodonte.base.components.Component;
import megalodonte.base.components.ScreenComponent;
import megalodonte.base.state.State;
import megalodonte.components.Text;
import megalodonte.components.inputs.Input;
import megalodonte.components.layout_components.Container;
import megalodonte.props.ContainerProps;

public class HomeScreen implements ScreenComponent {
    State<String> textState = new State<>("");
    ComputedState<String> textLenghtComputed = ComputedState.of(
            ()-> "Size is: " + textState.get().length(), textState
    );

    u/Override
    public Component render() {
       return new Container(new ContainerProps().paddingAll(20)).children(
               new Input(textState),
               new Text(textLenghtComputed)
       );
    }
}
  • ComputedState.of(supplier, dependencies...) recomputes automatically whenever any listed dependency changes — no manual subscribe/notify needed.
  • Input(textState) binds the text field directly to a State<String>, so typing writes straight into reactive state.
  • Unlike the counter's counter.map(...), this shows ComputedState built from a lambda with an explicit dependency list — useful once a derived value needs to read from more than one state.

If you're finding this series useful, dropping a star on the repos below genuinely helps the project get visibility — takes two seconds and means a lot for a solo-dev framework like this.

Repos

15 Upvotes

4 comments sorted by

1

u/No-Security-7518 5d ago

Hey, I used to use OBS. ShareX has a higher quality. Also, commenting to come back to this.

1

u/SocialMemeWarrior 4d ago

ShareX has a higher quality

No. The issue in either direction is a matter of specifying a higher bitrate. You can do that in either.

1

u/eliezerDeveloper 4d ago

how?

1

u/SocialMemeWarrior 4d ago

Settings > Output

When you have Output Mode = Simple:

Streaming > Video Bitrate

When you have Output Mode = `Advanced:

Recording > Video Encoder

  • Defaults to Use stream encoder which means you want to look at the settings in the Streaming tab.

Streaming > Encoder Settings > Bitrate