JavaFX Events
Handling user interactions and system events
⚡ What are Events?
JavaFX Events are notifications that occur when users interact with your application, such as clicking buttons, typing text, or moving the mouse. Event handling makes applications interactive and responsive.
// Simple Button Click Event
Button button = new Button("Click Me!");
button.setOnAction(event -> {
System.out.println("Button was clicked!");
});
Output:
Common Event Types
Mouse Events
Click, hover, drag interactions
node.setOnMouseClicked(e ->
handleClick());
Keyboard Events
Key press and release events
scene.setOnKeyPressed(e ->
handleKeyPress(e));
Action Events
Button clicks, menu selections
button.setOnAction(e ->
performAction());
Change Events
Property value changes
slider.valueProperty().addListener(
(obs, old, val) -> update());
🔹 Button and Action Events
The most common events in JavaFX applications:
// Different ways to handle button events
Button button1 = new Button("Lambda Style");
button1.setOnAction(event -> {
System.out.println("Lambda event handler");
// Your code here
});
Button button2 = new Button("Method Reference");
button2.setOnAction(this::handleButtonClick);
Button button3 = new Button("Anonymous Class");
button3.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Anonymous class handler");
}
});
// Method for method reference
private void handleButtonClick(ActionEvent event) {
Button source = (Button) event.getSource();
System.out.println("Button clicked: " + source.getText());
}
Output:
🔹 Mouse Events
Handling various mouse interactions:
Rectangle rectangle = new Rectangle(100, 100, Color.LIGHTBLUE);
// Mouse click events
rectangle.setOnMouseClicked(event -> {
if (event.getButton() == MouseButton.PRIMARY) {
System.out.println("Left click at: " + event.getX() + ", " + event.getY());
} else if (event.getButton() == MouseButton.SECONDARY) {
System.out.println("Right click detected");
}
});
// Mouse enter and exit (hover effects)
rectangle.setOnMouseEntered(event -> {
rectangle.setFill(Color.LIGHTGREEN);
rectangle.setCursor(Cursor.HAND);
});
rectangle.setOnMouseExited(event -> {
rectangle.setFill(Color.LIGHTBLUE);
rectangle.setCursor(Cursor.DEFAULT);
});
// Mouse drag events
rectangle.setOnMouseDragged(event -> {
rectangle.setX(event.getX() - 50);
rectangle.setY(event.getY() - 50);
System.out.println("Dragging to: " + event.getX() + ", " + event.getY());
});
Output:
🔹 Keyboard Events
Capturing and responding to keyboard input:
TextField textField = new TextField();
Label statusLabel = new Label("Type something...");
// Key pressed events
textField.setOnKeyPressed(event -> {
KeyCode key = event.getCode();
switch (key) {
case ENTER:
statusLabel.setText("Enter key pressed!");
break;
case ESCAPE:
textField.clear();
statusLabel.setText("Text cleared");
break;
case F1:
statusLabel.setText("Help key pressed");
break;
default:
statusLabel.setText("Key pressed: " + key.getName());
}
});
// Text change events
textField.textProperty().addListener((observable, oldValue, newValue) -> {
statusLabel.setText("Text changed to: " + newValue);
});
// Scene-level keyboard events
scene.setOnKeyPressed(event -> {
if (event.isControlDown() && event.getCode() == KeyCode.S) {
System.out.println("Ctrl+S pressed - Save action");
event.consume(); // Prevent default behavior
}
});
Output:
🔹 Property Change Events
Listening to property changes in JavaFX components:
Slider slider = new Slider(0, 100, 50);
Label valueLabel = new Label("Value: 50");
ProgressBar progressBar = new ProgressBar(0.5);
// Listen to slider value changes
slider.valueProperty().addListener((observable, oldValue, newValue) -> {
int intValue = newValue.intValue();
valueLabel.setText("Value: " + intValue);
progressBar.setProgress(intValue / 100.0);
});
CheckBox checkBox = new CheckBox("Enable notifications");
Label checkStatus = new Label("Notifications: OFF");
// Listen to checkbox state changes
checkBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
checkStatus.setText("Notifications: " + (newValue ? "ON" : "OFF"));
});
ComboBox<String> comboBox = new ComboBox<>();
comboBox.getItems().addAll("Option 1", "Option 2", "Option 3");
Label comboStatus = new Label("No selection");
// Listen to combo box selection changes
comboBox.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> {
comboStatus.setText("Selected: " + newValue);
}
);
Output:
🔹 Event Handling Best Practices
Tips for effective event handling in JavaFX:
Best Practices:
- Use Lambda Expressions: More concise and readable for simple handlers
- Separate Logic: Keep event handlers simple, delegate complex logic to methods
- Event Consumption: Use event.consume() to prevent event bubbling when needed
- Weak References: Use weak listeners for long-lived objects to prevent memory leaks
- Thread Safety: Update UI components only from the JavaFX Application Thread
// Good practice example
public class EventHandlingExample extends VBox {
private TextField inputField;
private Label outputLabel;
public EventHandlingExample() {
setupUI();
setupEventHandlers();
}
private void setupUI() {
inputField = new TextField();
outputLabel = new Label("Enter text above");
Button processButton = new Button("Process");
getChildren().addAll(inputField, processButton, outputLabel);
setSpacing(10);
}
private void setupEventHandlers() {
// Simple lambda for button
Button processButton = (Button) getChildren().get(1);
processButton.setOnAction(e -> processInput());
// Method reference for text changes
inputField.textProperty().addListener(this::onTextChanged);
}
private void processInput() {
String text = inputField.getText();
if (!text.isEmpty()) {
outputLabel.setText("Processed: " + text.toUpperCase());
}
}
private void onTextChanged(ObservableValue<? extends String> obs,
String oldText, String newText) {
if (newText.length() > 50) {
inputField.setText(oldText); // Limit input length
}
}
}