Zephyr Zephyr - 2 months ago 42
Java Question

(JavaFX) Unable to use controls when binding the textProperty()?

I'm just getting started in learning property binding. I have my controls set and the properties bound here (code abbreviated):

@FXML
private TextField txtOldPremium;
@FXML
private TextField txtNewPremium;
@FXML
private TextField txtProratedChange;

private SimpleBooleanProperty quoteOnly = new SimpleBooleanProperty();
private SimpleBooleanProperty reviewedBilling = new SimpleBooleanProperty();
private SimpleStringProperty oldPremium = new SimpleStringProperty();
private SimpleStringProperty newPremium = new SimpleStringProperty();
private SimpleStringProperty proratedChange = new SimpleStringProperty();
private SimpleStringProperty additionalInformation = new SimpleStringProperty();

@FXML
public void initialize() {

// Bind the vehicle data to the tableview
colEffectiveDate.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("effectiveDateString"));
colDescription.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("description"));
colVIN.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("vin"));
colAction.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("action"));

// Setup data binding to controls
chkQuoteOnly.selectedProperty().bindBidirectional(quoteOnly);
chkReviewedBilling.selectedProperty().bindBidirectional(reviewedBilling);
txtOldPremium.textProperty().bindBidirectional(oldPremium);
txtNewPremium.textProperty().bindBidirectional(newPremium);
}

@Override
public String getComments() {
StringBuilder comments = new StringBuilder();

if (!txtOldPremium.getText().isEmpty() && !txtNewPremium.getText().isEmpty()) {

} else {

}
}
if (!txtProratedChange.getText().isEmpty()) {

}


I am getting a NullPointerException at
if (!txtOldPremium.getText().isEmpty() && !txtNewPremium.getText().isEmpty()) {
. I am assuming I am doing something radically wrong with implementing the bindings. The TextFields themselves are currently empty.

Basically, I just want the
TextField
and the
oldPremium
String to always remain in sync with eachother. But I still need to be able to do processing on the text
TextField
. I do have several other types of controls (
CheckBox
,
ComboBox
, etc) that I want to have sync with the underlying data.

Answer

You are binding the text properties of the text fields to StringProperty instances that have been created without an initial value. So, for example, when you do

private SimpleStringProperty oldPremium = new SimpleStringProperty();

you create oldPremium without an actual value. So oldPremium.getValue() will return null.

So then when you do

txtOldPremium.textProperty().bindBidirectional(oldPremium);

you synchronize the state of the two properties (txtOldPremium.textProperty() and oldPremium), which involves copying the value of oldPremium (which is null) into txtOldPremium.textProperty().

So just initialize the properties to hold an empty string, instead of null:

private SimpleStringProperty oldPremium = new SimpleStringProperty("");

etc.

Also, though, note that in this particular example you can achieve the same thing without duplicating all the properties. I.e. you can just do

private StringProperty oldPremium ;

// ...

@FXML
public void initialize() {

    // ...

    oldPremium = txtOldPremium.textProperty();

    // ...

}

You can still define property accessor methods

public StringProperty oldPremiumProperty() {
    return oldPremium ;
}

public final String getOldPremium() {
    return oldPremiumProperty().get();
}

public final void setOldPremium(String oldPremium) {
    oldPremiumProperty().set(oldPremium);
}

as you presumably already have, and it will have exactly the same effect, but with less overhead.

Bidirectional bindings are really most useful for synchronizing properties that belong to two different objects (e.g. properties belonging to different controllers, or to a controller and a model). Maybe your question reduced the code to demonstrate the problem, but I thought I would point this out for other users.

Comments