Search code examples
javabindingjavafx-8

Complex binding situation


In a javafx scene I have:

  • A combobox with some locales as items

  • A hashtable with entries (Locale, String)

  • A textfield to show and edit text

enter image description here

What I want to do is:

  • When locale combobox change, textield show the text stored in the hashtable according to locate selected. Example 1: if frech is selected, textfield shows 'french text'. Example 2: if chinese is selected, textfield doesn't show anything (hashtable doesn't contains zh key).

  • As some text is being typed in textfield, hashtable execute a put with the locale selected in combobox. Example 1: if 'aaa' is typed and french is selected, hashtable modify the entry fr with the text 'aaa'. Example 2: if 'bbb' is typed and chinese is selected, hastable add the entry (zh,'bbb'). Example 3: if textfiled has no text and english is selected, hashtable removes en entry.

Initially hashtable haven't empty strings and combobox always have a locate selected. Is it possible to achieve this?


Solution

  • By using a String object in your Hashtable you cannot use any Property's binding method to interact with it, but you should still be able to accomplish your goal by using listeners on these properties. Here is a rough example:

    public class Controller {
    
        private VBox base = new VBox();
        private ComboBox<Locale> comboBox = new ComboBox<>();
        private TextField textField = new TextField();
        private Button button = new Button("Print");
    
        private Hashtable<Locale, String> map = new Hashtable<>();
    
        public VBox getBase() {
            return base;
        }
    
        public Controller() {
            setupUi();
    
            addItem("Chinese");
            addItem("French");
            addItem("English");
            comboBox.getItems().add(new Locale("Russia", "Some Russian Text"));
    
            comboBox.getSelectionModel().selectedItemProperty()
                    .addListener((obs, oldVal, newVal) -> textField.setText(map.get(newVal)));
    
            textField.textProperty().addListener((obs, oldVal, newVal) -> {
                if (newVal == null || newVal.equals("")) {
                    map.remove(comboBox.getValue());
                } else {
                    map.put(comboBox.getValue(), newVal);
                }
            });
    
            comboBox.getSelectionModel().selectFirst();
        }
    
        private void setupUi() {
            base.getChildren().addAll(comboBox, textField, button);
            button.setOnAction(event -> System.out.println(map));
        }
    
        private void addItem(String name) {
            Locale locale = new Locale(name, String.format("Some %s text", name));
            map.put(locale, locale.text);
            comboBox.getItems().add(locale);
        }
    
    }
    
    
    class Locale {
    
        String name;
        String text;
    
        Locale(String name, String text) {
            this.name = name;
            this.text = text;
        }
    
        @Override
        public String toString() {
            return name;
        }
    
    }