UI logic with using JavaFX Bindings
For MQTT.fx I needed a ComboBox to enter new Topics or to choose recent topics from list.
But I want the user to enter or choose only (more or less) reasonable values otherwise the “Publish”/”Subscribe” buttons should be disabled:
Using the JavaFX Bindings API prevents some boilerplate code (implementing Listeners) and it is even more flexible as the result can be bound to several controls and at the end of the day its much more readable.
Contraint 1: The selection must not be empty.
- First create a JavaFX BooleanBinding.
- Then bind it to the disabledProperty of the button.
Contraint 2: Entered values must not contain only blanks (leading/trailing blanks can be trimmed later).
My approach is to
- add an EventFilter and to consume the event in case of only entered character is “SPACE”
- and if there are just blanks left when editing the value the content is cleared.
public class ComboBoxBindingsDemoController { @FXML private Label valueLabel; @FXML private Button goButton; @FXML private ComboBox<String> valueComboBox; private ObservableList<String> demoItemsList; private static final Pattern LEADING_BLANKS_PATTERN = Pattern.compile("^\\s*+"); @FXML public void initialize() { valueComboBox.setItems(getDemoItemsList()); BooleanBinding goButtonState = valueComboBox.editorProperty().get().textProperty().isEmpty() .or(valueComboBox.valueProperty().asString().isEmpty()); goButton.disableProperty().bind(goButtonState); valueComboBox.getEditor().addEventFilter(KeyEvent.KEY_TYPED, (KeyEvent event) -> { Matcher matcher = LEADING_BLANKS_PATTERN.matcher(valueComboBox.getEditor().getText()); if (" ".equals(event.getCharacter()) && valueComboBox.getEditor().getText().length() == 0) { event.consume(); } else if(matcher.matches()){ valueComboBox.getEditor().clear(); } }); } public ObservableList<String> getDemoItemsList() { if (demoItemsList == null) { demoItemsList = FXCollections.observableArrayList(); demoItemsList.add("Erlangen"); demoItemsList.add("Nürnberg"); demoItemsList.add("Büchenbach"); } return demoItemsList; } @FXML public void goAction() { System.out.println("Value '" + valueComboBox.getValue().trim() + "'"); } }
Complete runnable demo can be found at Bitbucket.
Leave a Reply