Search code examples
stringjavafxbindingtableviewobservablelist

Biding StringProperty to position in list Javafx


I am trying to create an ObservableList() to use with my Tableview. The StringData type is a class containing two SimpleStringProperty var. I want to create this list and bind each variable to an specific position of a List. Something like this:

public class DownloadService implements Runnable {
       //List that will be updated
       public List<SimpleStringProperty> dList = new ArrayList<SimpleStringProperty>();

public class MainScreenController implements Initializable {
    //List that populates TV    
    private ObservableList<DataString> data = FXCollections.observableArrayList();
    //tableview        
    @FXML
    private TableView<DataString> tbl_table;
    DownloadService download;
 ...}


public class DataString{

    public final SimpleStringProperty state;
    public final SimpleStringProperty sinc;

    public SimpleStringProperty stateProperty() {
        return state;
    }

    public void setState(String status) {
        state.set(status);
    }

    public SimpleStringProperty sincProperty() {
        return sinc;
    }

    public void setSinc(String sinc) {
        this.sinc.set(sinc);
    }
}

On MainScreenController I try to do this:

DataString s = new DataString();
s.state.bind (download.dList.get(data.size()));
s.sinc.bind (download.dList.get(data.size()));
data.add(s);

tbl_table.setItems(data);

However, I cannot update the content of data when I update the list on DownloadService. I believe it should update the value of the column associated with the state and sinc variable everytime DownloadService updated the content of the list in each position. I am doing something wrong or is there another way to bind a StringProperty to a position on the list?

Thanks!


Solution

  • You are binding to the specific object inside the list, not to the position. If using SimpleStringProperty in dList isn't strict requirement, than you can use Bindings.stringValueAt():

    StringBinding binding = Bindings.stringValueAt(dList, index);
    s.state.bind(binding);
    

    If you really need SimpleStringProperty, you can implement custom StringBinding, something like this:

    class CustomStringBinding extends StringBinding {
    
        private ObservableList<SimpleStringProperty> op;
        private int index;
    
        public CustomStringBinding(ObservableList<SimpleStringProperty> list, int index) {
            this.op = list;
            this.index = index;
            super.bind(op, op.get(index));
        }
    
        @Override
        public void dispose() {
            super.unbind(op, op.get(index));
        }
    
        @Override
        protected String computeValue() {
            try {
                return op.get(index).get();
            } catch (IndexOutOfBoundsException ex) {
                // log
            }
            return null;
        }
    
        @Override
        public ObservableList<?> getDependencies() {
            return FXCollections.singletonObservableList(op);
        }
    }