I have the following tableView in fxml
<TableView fx:id="tableView" prefHeight="525.0" prefWidth="814.0">
<columns>
<TableColumn prefWidth="75.0">
<graphic><ToggleButton fx:id="mainToggleButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" onAction="#onMainToggleButtonAction" text="Start all" /></graphic>
<cellFactory><ToggleButtonTableCellFactory maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" activatedText="Started" deactivatedText="Stopped"/></cellFactory>
<cellValueFactory><PropertyValueFactory property="state"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Side">
<cellValueFactory><PropertyValueFactory property="side"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Source">
<cellValueFactory><PropertyValueFactory property="sourceContract"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Reference" editable="true">
<cellFactory>
<ChoiceBoxTableCellFactory maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="r01" />
<String fx:value="r02" />
</FXCollections>
</items>
</ChoiceBoxTableCellFactory>
</cellFactory>
<cellValueFactory><PropertyValueFactory property="referenceContract"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Destination">
<cellValueFactory><PropertyValueFactory property="destinationContract"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Margin" editable="true">
<cellFactory><SpinnerTableCellFactory maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="0" max="1" initialValue="0" amountToStepBy="0.025" decimalFormat="0.000"/></cellFactory>
<cellValueFactory><PropertyValueFactory property="margin"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Bot">
<cellValueFactory><PropertyValueFactory property="bot"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Price">
<cellValueFactory><PropertyValueFactory property="price"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Volume">
<cellValueFactory><PropertyValueFactory property="volume"/></cellValueFactory>
</TableColumn>
</columns>
<items>
<FXCollections fx:factory="observableArrayList">
<GridRowModel state="false" side="BID" sourceContract="s01" referenceContract="r01" destinationContract="d01" margin="0" bot="MinMax" price="15.125" volume="0" />
<GridRowModel state="false" side="ASK" sourceContract="s02" referenceContract="r01" destinationContract="d02" margin="0" bot="MinMax" price="15.125" volume="0" />
</FXCollections>
</items>
</TableView>
The ChoiceBoxTableCellFactory
has a constructor which takes both named arguments from the fxml and a setter for the items element.
public class ChoiceBoxTableCellFactory<S, T> implements Callback<TableColumn<S, String>, TableCell<S, String>> {
private ObservableList<String> items;
private double maxHeight;
private double maxWidth;
public ChoiceBoxTableCellFactory() {
}
public ChoiceBoxTableCellFactory(
@NamedArg("maxHeight") double maxHeight,
@NamedArg("maxWidth") double maxWidth) {
this.maxHeight = maxHeight;
this.maxWidth = maxWidth;
}
@Override
public TableCell<S, String> call(TableColumn<S, String> param) {
return new TableCell<S, String>() {
ChoiceBox<String> choiceBox = new ChoiceBox<>(getItems());
{
choiceBox.setMaxHeight(maxHeight);
choiceBox.setMaxWidth(maxWidth);
choiceBox.valueProperty().addListener((obs, oldValue, newValue) -> {
ObservableValue<String> value = getTableColumn().getCellObservableValue(getIndex());
if (value instanceof WritableValue) {
((WritableValue<String>) value).setValue(newValue);
}
});
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setText(null);
setGraphic(null);
} else {
choiceBox.setValue(item);
setText(null);
setGraphic(choiceBox);
}
}
}
};
}
public ObservableList<String> getItems() {
return items;
}
public void setItems(ObservableList<String> items) {
this.items = items;
}
}
But that throws this exception
Caused by: java.lang.IllegalArgumentException: Unable to coerce [[r01, r02]] to interface javafx.collections.ObservableList.
at com.sun.javafx.fxml.BeanAdapter.coerce(BeanAdapter.java:496)
at com.sun.javafx.fxml.builder.ProxyBuilder$Setter.invoke(ProxyBuilder.java:533)
at com.sun.javafx.fxml.builder.ProxyBuilder.createObjectFromDefaultConstructor(ProxyBuilder.java:338)
... 144 more
When I remove the maxHeight
and maxWidth
attributes the items field is set correctly through the setter. With these attributes the items value is wrapped in an additional array. How can I achieve the desired result?