Reputation: 511
I want to add a change listener for every control in a panel. I want it to be robust, so whenever I change fxml file, I wouldn't have to alter the code that listens for changes in controls.
I have figured a way to add a listener for a specific type of control.
panel.getChildren()
.stream()
.filter(node -> node instanceof TextField).forEach(node ->
((TextField) node).textProperty()
.addListener((observable, oldValue, newValue) -> {
//execute some code
}));
However I would need to a add similar code to every type of control I intend to use in a panel for this to work.
panel.getChildren()
.stream()
.filter(node -> node instanceof TextField).forEach(node ->
((TextField) node).textProperty()
.addListener((observable, oldValue, newValue) -> {
//execute some code
}));
panel.getChildren()
.stream()
.filter(node -> node instanceof TextArea).forEach(node ->
((TextArea) node).textProperty()
.addListener((observable, oldValue, newValue) -> {
//execute some code
}));
//and so on...
panel.getChildren()
.stream()
.filter(node -> node instanceof ComboBox).forEach(node ->
((ComboBox<?>) node).valueProperty()
.addListener((observable, oldValue, newValue) -> {
//execute some code
}));
What I want to do is.
I've a document editor that has a panel with controls, so whenever user changes one of that controls preset value, panel with save and cancel buttons would be enabled. Also if user tried to exit a program, without canceling or saving a document, a warning would pop up asking him if he wants to discard changes and exit or cancel.
However I intend to do a lot of changes to document structure, so I will need to add and remove controls from panel constantly. So I need the best way to add this type of listener for every control in a panel in one go.
Upvotes: 1
Views: 758
Reputation: 2734
you should write (extend) your own controls and use them in your application. In them you can implement all specific tracking logic as @James_D mentioned. Such an extended TextField should look like this:
public class TrackableTextField extends javafx.scene.control.TextField {
private StringProperty originalText = new ReadOnlyStringWrapper(this, "originalText");
public final String getOriginalText() { return originalText.get(); }
public final void setOriginalText(String value) {
originalText.set(value);
setText(value);
}
public final StringProperty originalTextProperty() { return originalText; }
private final ReadOnlyBooleanWrapper dirty = new ReadOnlyBooleanWrapper(this, "dirty", false);
public final boolean isDirty() { return dirty.get(); }
public final ReadOnlyBooleanProperty dirtyProperty() { return dirty.getReadOnlyProperty(); }
public TrackableTextField() {
init();
}
public TrackableTextField(String text) {
init();
setOriginalText(text);
}
private void init() {
textProperty().addListener( e -> {
dirty.set(!Objects.equals(getOriginalText(), getText()));
} );
}
public void rollback() {
setText(getOriginalText());
}
public void commit() {
setOriginalText(getText());
}
}
and a usage example may be like
public class Test extends Application {
private TrackableTextField tf_name = new TrackableTextField();
private TrackableTextField tf_sname = new TrackableTextField();
private Button save = new Button("Save");
private Button discard = new Button("Discard");
@Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
root.add(new Label("Name: "), 0, 0);
root.add(tf_name, 1, 0);
root.add(new Label("Surname: "), 0, 1);
root.add(tf_sname, 1, 1);
root.add(save, 0, 2);
root.add(discard, 1, 2);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
initialize();
}
private void initialize() {
save.setDisable(true);
discard.setDisable(true);
save.disableProperty().bind(tf_name.dirtyProperty().or(tf_sname.dirtyProperty()).not());
discard.disableProperty().bind(tf_name.dirtyProperty().or(tf_sname.dirtyProperty()).not());
tf_name.setOriginalText("guleryuz");
tf_sname.setOriginalText("guleryuz");
save.setOnAction( e -> {
tf_name.commit();
tf_sname.commit();
} );
discard.setOnAction( e -> {
tf_name.rollback();
tf_sname.rollback();
} );
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 2