Cell factory for variable Property



  • There are two types in the model class. Property: SimpleStringProperty and SimpleIntegerProperty♪ They need to be displayed in shape TableViewwhere the first column is the name of the meaning (description) and the second is the same. Something like that:

    введите сюда описание изображения

    Data from class models are packed in Map<String,Property<?>>where key is the name of the value, and value - Property with meaning.

    Interests:

    (1) How the CellValueFactory should look, so that the values are correctlybinden, i.e., if necessary, could be changed in the table and the changes reflected in the model class.

    (2) Are the jerricans in the mape-pack?

    UPD: I added an intermediate class to deal with this issue, but I think there's a code:

    public class PropertiesContainer {
        private String propName;
        private SimpleIntegerProperty concreteIntSourceProperty=null;
        private SimpleStringProperty concreteStrSourceProperty=null;
        private SimpleStringProperty destProperty;
    
    public PropertiesContainer(String propName, Property&lt;?&gt; property) {
        this.propName = propName;
        if (property.getClass().equals(SimpleStringProperty.class)){
            concreteStrSourceProperty = (SimpleStringProperty) property;
            destProperty = new SimpleStringProperty(concreteStrSourceProperty.get());
        }
        else if (property.getClass().equals(SimpleIntegerProperty.class)) {
            concreteIntSourceProperty = (SimpleIntegerProperty) property;
            destProperty = new SimpleStringProperty(Integer.toString(concreteIntSourceProperty.get()));
        }
    
        destProperty.addListener((observable, oldValue, newValue) -&gt; {
            if (concreteIntSourceProperty!=null) concreteIntSourceProperty.set(Integer.valueOf(newValue));
            else concreteStrSourceProperty.set(newValue);
        });
    }
    public String getDestProperty() {
        return destProperty.get();
    }
    public SimpleStringProperty destProperty() {
        return destProperty;
    }
    public String getPropName() {
        return propName;
    }
    

    }



  • I'll start with an expanded example from http://docs.oracle.com/javafx/2/ui_controls/table-view.htm :

    public class TableViewSample extends Application {
    
    public static final String Column1MapKey = "String";
    public static final String Column2MapKey = "Integer";
    
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View");
        stage.setWidth(300);
        stage.setHeight(500);
    
        final Label label = new Label("TODO List");
        label.setFont(new Font("Arial", 20));
    
        TableColumn&lt;Map, String&gt; firstDataColumn = new TableColumn&lt;&gt;("Description");
        TableColumn&lt;Map, String&gt; secondDataColumn = new TableColumn&lt;&gt;("Value");
    
        firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
        firstDataColumn.setMinWidth(130);
        secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
        secondDataColumn.setMinWidth(130);
    
        TableView table_view = new TableView&lt;&gt;(generateDataInMap());
    
        table_view.setEditable(true);
        table_view.getSelectionModel().setCellSelectionEnabled(true);
        table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
    
        firstDataColumn.setCellFactory(new Callback&lt;TableColumn&lt;Map, String&gt;, TableCell&lt;Map, String&gt;&gt;() {
    
            @Override
            public TableCell call(TableColumn p) {
                return new TextFieldTableCell(new DefaultStringConverter());
            }
        });
    
        secondDataColumn.setCellFactory(new Callback&lt;TableColumn&lt;Map, String&gt;, TableCell&lt;Map, String&gt;&gt;() {
    
            @Override
            public TableCell call(TableColumn p) {
                return new TextFieldTableCell(new IntegerStringConverter());
            }
        });
    
        final VBox vbox = new VBox();
    
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table_view);
    
        ((Group) scene.getRoot()).getChildren().addAll(vbox);
    
        stage.setScene(scene);
    
        stage.show();
    }
    
    private ObservableList&lt;Map&gt; generateDataInMap() {
        int max = 10;
        ObservableList&lt;Map&gt; allData = FXCollections.observableArrayList();
        for (int i = 1; i &lt; max; i++) {
    
            Map&lt;String, Property&lt;?&gt;&gt; dataRow = new HashMap&lt;&gt;();
    
            SimpleStringProperty value1 = new SimpleStringProperty("string " + i);
            SimpleIntegerProperty value2 = new SimpleIntegerProperty(i);
    
            dataRow.put(Column1MapKey, value1);
            dataRow.put(Column2MapKey, value2);
    
            allData.add(dataRow);
        }
        return allData;
    }
    

    }

    And on the question:

    Call attention to the CellValueFactory method - fills boxes, while the dynamic change is the result of the setCellFactory method, which, through a long chain, is responsible for interaction with the Property object - the original example shows the work with the abstract Class StringConverter - a good way out of many situations.

    Yeah, great janerik.

    UPD:
    Like SimpleObjectProperty

    Bread class:

    class Wrapper {

    class InnerWrapper&lt;T&gt; extends SimpleObjectProperty&lt;T&gt; {
    
        @Override
        public void set(T newValue) {
            T temp = null;
            if (newValue.getClass().equals(Integer.class))
                temp = newValue;
            else
                temp = (T) (((String) newValue).matches("\\d+") ? Integer.valueOf((String) newValue) : newValue.toString());
            super.set(temp);
        }
    
    }
    
    private InnerWrapper inner = new InnerWrapper();
    
    public Object getNut() {
        return nutProperty().get();
    }
    
    public final SimpleObjectProperty nutProperty() {
        return inner;
    }
    
    public void setNut(Object candiate) {
        nutProperty().set(candiate);
    }
    

    }

    Example of factory:

        firstDataColumn.setCellValueFactory(new Callback<CellDataFeatures<Map, String>, ObservableValue<String>>() {
    public ObservableValue<String> call(CellDataFeatures<Map, String> p) {
    return ((Wrapper)p.getValue().get(Column1MapKey)).nutProperty();
    }
    });




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2