Sunday, February 18, 2018

Dynamically adding JavaFX controls

Dynamically adding JavaFX controls


The JavaFX SceneBuilder works very well for constructing a static GUI; that is, a GUI whose controls are determined entirely at compile-time.  But sometimes it is useful to be able to add new controls dynamically at run-time.  The example below demonstrates one way to do this.

In this example, the user creates Button objects on-the-fly.  They are displayed using a ListViewer and stored in an ObservableList.  Each button inverts the capitalization of its label when clicked.  The Controller class is given below; constructing the rest of the GUI is an exercise for the reader.

package application;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;

public class Controller {
@FXML
private Button add;
@FXML
private TextField button;
@FXML
private ListView<Button> visibleList;

private ObservableList<Button> buttons =
FXCollections.observableArrayList();

@FXML
protected void initialize() {
visibleList.setItems(buttons);
}

@FXML
void addName() {
Button b = new Button(button.getText());
buttons.add(b);
b.addEventHandler(MouseEvent.MOUSE_CLICKED,
(event -> b.setText(invertCapitals(b.getText()))));
button.setText("");

}

public static String invertCapitals(String other) {
return other.chars().mapToObj(Controller::flipCap)
.map(c -> Character.toString(c))
.reduce("", (s, c) -> s + c);
}

public static Character flipCap(int c) {
if (c >= A && c <= Z) {
return (char)(c - A + a);
} else if (c >= a && c <= z) {
return (char)(c - a + A);
} else {
return (char)c;
}
}
}

Highlighted in red, the key to making this all work is the addName() method, working in combination with the ObservableList buttons.   This method creates a new Button object in response to every click of the add button.  This object is added to our ObservableList, which makes it visible in the ListViewer.  Finally, we employ a Java 8 lambda to implement the event handler.

There is a pretty long list of event types to which one might respond.  Check out the documentation for the MouseEvent and KeyEvent classes to get started.

Heres a sample run of the program:


visit link download