We are still cooking the magic in the way!
Handling a Simple Event
Handling a Simple Event
Every interactive GUI revolves around one central idea: something happens — the user clicks a button, presses a key, moves the mouse — and your code reacts. In JavaFX this is formalised through the event system. This lesson focuses tightly on the most common case you will write dozens of times: responding to a Button click. Once you understand how that works, every other event type follows the same pattern.
How the JavaFX Event System Works
When the user clicks a button, JavaFX constructs an ActionEvent object and delivers it to any registered event handler. An event handler is an object that implements EventHandler<T extends Event>, a functional interface with a single method:
Because EventHandler is a functional interface, you can supply a handler as a lambda expression instead of writing an anonymous class. That is the idiomatic approach in modern JavaFX.
Registering a Handler with setOnAction
Button (and every other control that fires action events) exposes the convenience method setOnAction(EventHandler<ActionEvent> handler). You pass your lambda there and JavaFX calls it every time the button is activated — whether by mouse click, keyboard (Space/Enter), or touch.
Walk through the important points:
- The lambda captures
countandlabelfrom the enclosing scope. Becausecountis a field (not a local variable), mutation inside the lambda is perfectly legal. - The
ActionEventparameter is available inside the lambda but ignored here — it is useful when one handler is shared by multiple controls and you need to know which one fired. - Updating
label.setText(...)inside the handler is safe becausesetOnActionhandlers always execute on the JavaFX Application Thread.
Shorter Syntax: Dropping the Parameter Type
Java can infer the parameter type from context, so you can shorten the lambda:
If the body is a single expression, you can drop the braces and semicolon entirely:
Using a Method Reference
When the handler logic is substantial enough to deserve its own method — or when the same logic is reused from multiple places — extract it as an instance method and pass a method reference:
start() method that already constructs the scene graph. Extracting to a named method also makes it trivially testable in isolation.
One Handler, Multiple Buttons
When several buttons share the same response logic, register the same handler for all of them and use the event source to distinguish which button was clicked:
event.getSource() returns the Object that fired the event — cast it to Button and inspect its text, its user data (setUserData / getUserData), or its id (setId / getId) to branch your logic cleanly.
button.getId() or a dedicated enum stored via setUserData() instead. The text comparison above is used here only for brevity.
addEventHandler vs setOnAction
The setOnAction shorthand registers exactly one handler; a second call replaces the first. When you need multiple independent handlers on the same control, use the lower-level API:
To remove a specific handler later, keep a reference to the lambda (you cannot remove an anonymous lambda), or use a named method reference:
Summary
Handling a button click in JavaFX follows a clear three-step pattern: create the button, register a handler via setOnAction (or addEventHandler), and mutate the scene graph inside that handler. Use lambdas for concise inline logic and method references when the handler deserves a name. Because handlers fire on the JavaFX Application Thread, you can update the UI directly — no synchronisation needed. In the next lesson you will see what happens when handler work takes too long and how to offload it to a background thread without freezing the UI.