- COMP.CS.140
- 12. Graphical User Interfaces
- 12.2 JavaFX Library
- 12.2.2 First JavaFX Program
First JavaFX Program¶
A JavaFX program consists of two containers: a stage and a scene.
Stage
is the top-most level container and it presents the entire windowScene
is the container that contains all the content shown in the window.
The contents of the scene is the content of the screen.
The nodes i.e. drawable UI elements are added to a root node e.g. StackPane
or FlowPane
, that defines theis location on the screen.
A simple JavaFX program with an event is thus:
package example;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) {
// Create a button to the UI
Button printButton = new Button();
// add the text "Print" to it
printButton.setText("Print");
// Create also a text field
TextField output = new TextField();
// and a preferred width to it in pixels
output.setPrefWidth(250);
// Create a pane for the UI elements
// FlowPane sets its elements horizontally or vertically
// by default horizontally
var group = new FlowPane();
// Add the elements to their pane
group.getChildren().add(printButton);
group.getChildren().add(output);
// All can be added at the same time: group.getChildren().addAll(printButton, output);
// Create a scene and add the pane to it
Scene scene = new Scene(group, 300, 150);
// add the scene to the stage
stage.setScene( scene );
stage.setTitle("All the world's a stage");
// and show the stage
stage.show();
}
public static void main(String[] args) {
launch( args );
}
}
At this point our program looks like this:
Our program doesn’t do anything yet. We need to add an event handler for our button.
An event is handled with an object that implements the interface EventHandler
.
Pressing a button causes an ActionEvent
.
Let’s add an event handler for printButton
before creating the scene:
// an event handler is always defined for a UI element
// it tells what functionality is needed when the event occurs
// here the press of the button writes text into the text field
printButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// Note! objects used in the handler
// must be declared before the handler implementation
output.setText("And all the men and women merely players;");
}
});
When a node in the UI connected to the handler performs the operation, the event handler registered to the node. Now our program looks like this after a button press:
The event handler can be defined also with a lambda function:
printButton.setOnAction((event) -> {
output.setText("And all the men and women merely players;");
});
As mentioned earlier the type of the eventhandler depends on the type of the UI node it is connected to.
Key presses are handled by KeyEvent
so a handler clearing the text field after enter is pressed would be implemented with:
printButton.setOnKeyPressed( new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent k) {
if (k.getCode().equals(KeyCode.ENTER)) {
output.clear();
}
}
});
Additionally, if we want to follow for changes in some property of a node a changeListener
can be registered as the event handler.
For example changes to a slider would be listened to with slider.valueProperty.addListener( new ChangeListener<Number>)
handler where
@Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
would be implemented.