Controlling UI state

IA tooling, not an exam topic. These recipes are JavaFX patterns to adapt for your own Internal Assessment app. Nothing here is examinable. Your IA must be your own work, so treat each snippet as a part to change, not a feature to copy.

This page is about controlling what the user can do right now: turning controls on and off, showing why something is off, putting the cursor in the right place, and letting the Enter key do the obvious thing.


Turn a control on or off depending on what is happening

What this does: switches a control between usable and not usable, so the user can only take actions that make sense at the moment.

When you would use it in your IA: a Save button that stays off until the form has the data it needs; a Delete button that only works once a row is selected; a Next button that waits until the current step is complete.

The pattern:

Imports:

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

Controller fields and logic:

@FXML private Button btnSave;
@FXML private TextField txtName;

@FXML
public void initialize() {
    btnSave.setDisable(true);          // start off until there is something to save
}

// Call this whenever the inputs change (for example from the field's onKeyReleased).
@FXML
private void updateButtons() {
    boolean ready = !txtName.getText().trim().isEmpty();
    btnSave.setDisable(!ready);        // on when ready, off when not
}

FXML (the field calls the update method as the user types):

<TextField fx:id="txtName" onKeyReleased="#updateButtons" />
<Button fx:id="btnSave" text="Save" onAction="#handleSave" />

Make it your own:

  • Replace the ready condition with whatever “allowed right now” means in your app (a row selected, two fields filled, a total above zero).
  • Rename updateButtons and call it from every place that changes those inputs.
  • setDisable(true) turns a control off, setDisable(false) turns it on. The value is “is it disabled”, so it reads backwards from “is it ready”.

Watch out for:

  • A disabled control still takes up space and stays visible, just greyed out and unclickable. If you want it gone entirely, that is setVisible(false) and setManaged(false) instead, which is a different choice.
  • Remember to call your update method from every input, not just one, or the button state will lag behind the data.

Mix with: Show the user why a control is off, Catch and explain bad input, Find out which row the user clicked.


Show the user why a control is off

What this does: makes a disabled control look clearly inactive and gives the reason on hover, so the user is not left guessing why a button does nothing.

When you would use it in your IA: any time a control is off for a reason the user might not work out on their own. A faded Submit button with a tooltip saying “Choose a date first” is friendlier than a button that silently ignores clicks.

The pattern:

Imports:

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Tooltip;

Controller:

@FXML private Button btnSubmit;

private void setSubmitEnabled(boolean enabled) {
    btnSubmit.setDisable(!enabled);
    btnSubmit.setOpacity(enabled ? 1.0 : 0.5);   // full strength on, half faded off
}

@FXML
public void initialize() {
    btnSubmit.setTooltip(new Tooltip("Fill in every field before submitting."));
    setSubmitEnabled(false);
}

Make it your own:

  • Change the tooltip text to name the exact reason the control is off.
  • 0.5 is just “half visible”. Use any value between 0.0 (invisible) and 1.0 (solid) to taste.
  • Call setSubmitEnabled(true) from your “is it ready” check, the same place as the previous recipe.

Watch out for:

  • Tooltips only appear on hover, so they are a hint, not a substitute for a visible message when something is genuinely wrong.
  • A control that is fully disabled does not receive mouse events, so a tooltip set directly on it may not show while it is disabled. If you need the hint to appear in the disabled state, put the Tooltip on the control’s parent container (for example the surrounding VBox) using Tooltip.install(parentNode, tip), or keep the control enabled and show a message on click instead.

Mix with: Turn a control on or off, Tell the user something.


Put the cursor where the user should start

What this does: moves the keyboard focus to a chosen control when the screen opens, so the user can start typing straight away without clicking first.

When you would use it in your IA: a login screen that should land on the username field; a search screen that should land on the search box; any form with an obvious first field.

The pattern:

Imports:

import javafx.fxml.FXML;
import javafx.scene.control.TextField;

Controller:

@FXML private TextField txtUsername;

@FXML
public void initialize() {
    txtUsername.requestFocus();      // this field is active when the window opens
}

Make it your own:

  • Change txtUsername to whichever control should be active first.
  • initialize() is the method JavaFX calls once the FXML has loaded, which is why it is the right place for opening setup.

Watch out for:

  • Occasionally the focus does not stick because the scene is still being built when initialize() runs. If that happens, wrap the call in Platform.runLater(() -> txtUsername.requestFocus()); so it runs just after the window is shown. That line uses a lambda, which is outside the exam-style Java subset but is the standard way to do this in JavaFX.
  • Only one control can hold focus at a time, so calling requestFocus() on several controls means the last one wins.

Mix with: Run setup code when a screen loads, React to the Enter key.


React to the Enter key

What this does: runs an action when the user presses Enter in a control, so they can submit a form or move on without reaching for the mouse.

When you would use it in your IA: pressing Enter in a search box to run the search; pressing Enter in the last field of a form to submit it; pressing Enter in a chat-style input to send.

The pattern:

Imports:

import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

Controller:

@FXML private TextField txtSearch;

@FXML
private void handleKeyPressed(KeyEvent event) {
    if (event.getCode() == KeyCode.ENTER) {
        runSearch();           // your own action
    }
}

FXML (the field sends key presses to the handler):

<TextField fx:id="txtSearch" onKeyPressed="#handleKeyPressed" />

Make it your own:

  • Replace runSearch() with the action you want Enter to trigger.
  • To react to a different key, compare against another KeyCode, for example KeyCode.ESCAPE to clear the field.
  • If you prefer to wire it in code rather than FXML, use txtSearch.setOnKeyPressed(e -> { ... });. That form uses a lambda, which is outside the exam-style subset but common in JavaFX.

Watch out for:

  • Put onKeyPressed on the control you want to listen to. If you put it on a container, key events only arrive when that container itself has focus.
  • A Button already fires its action on Enter when it has focus, so you usually only need this recipe for text fields and other inputs.

Mix with: Put the cursor where the user should start, Filter the table as the user types, Ask before doing something destructive.


© EduCS.me — A resource hub for Computer Science education

This site uses Just the Docs, a documentation theme for Jekyll.