如何用 ComboBox 填充 table 列单元格并观察?
How to populate table column cells with ComboBox and observe?
我的 table 视图有 2 列。第一个有我的对象的名称,第二个我想要一个 ComboBox,其值来自我的对象属性列表。
对 ComboBox 的任何更改都会将其 selected 属性更改为用户选择的列表元素。
例如:
| Name | Choices |
|---------------|-------------------|
| Object 1 Name | Object 1 ComboBox |
| Object 2 Name | Object 2 ComboBox |
到目前为止,我已经设法填充了名称,但我仍然停留在选择列中。
MyObject 模型:
public class MyObject {
// Objects name is the filename
private File file;
// Selection from the ComboBox that is populated with infoList elements
private SomeInfo selectedInfo;
private List<SomeInfo > infoList;
... getter/setter
控制器:
@FXML
private TableView<MyObject> myObjectTableView;
@FXML
private TableColumn<MyObject, String> myObjectNameTableColumn, myObjectChoicesTableColumn;
private void populateTableView(List<MyObject> myObjectList) {
ObservableList<MyObject> myObjectObservableList = FXCollections.observableList(myObjectList);
myObjectTableView.setItems(myObjectObservableList);
myObjectNameTableColumn.setCellValueFactory(c -> new SimpleStringProperty(c.getValue().getFile().getName()));
}
你的 myObjectChoicesTableColumn
类型有误。你需要
@FXML
private TableColumn<MyObject, List<SomeInfo>> myObjectChoicesTableColumn ;
那么你的cell value factory可以是
myObjectChoicesTableColumn.setCellValueFactory(cellData ->
new SimpleObjectProperty<>(cellData.getValue().getInfoList()));
要显示组合框,您需要一个单元工厂:
myObjectChoicesTableColumn.setCellFactory(col -> {
ComboBox<SomeInfo> combo ;
TableCell<MyObject, List<SomeInfo>> cell = new TableCell<MyObject, List<SomeInfo>>() {
@Override
protected void updateItem(List<SomeInfo> info, boolean empty) {
super.updateItem(info, empty);
if (empty) {
setGraphic(null);
} else {
MyObject rowItem = myObjectTableView.getItems().get(getIndex());
combo.getItems().setAll(info);
combo.setValue(rowItem.getSelectedInfo());
setGraphic(combo);
}
}
};
combo.valueProperty().addListener((obs, oldValue, newValue) ->
myObjectTableView.getItems().get(cell.getIndex()).setSelectedInfo(newValue));
return cell ;
}
您可能会发现重构模型更清晰,因此您可以将列表和所选项目包装在新的 class:
public class SelectableInfo {
private final ObservableList<SomeInfo> infoList = FXCollections.observableArrayList() ;
private SomeInfo selectedInfo ;
public ObservableList<SomeInfo> getInfoList() {
return infoList ;
}
public SomeInfo getSelectedInfo() {
return selectedInfo ;
}
public void setSelectedInfo(SomeInfo info) {
selectedInfo = info ;
}
}
和
public class MyObject {
private File file ;
private SelectableInfo selectableInfo ;
// getters and setters...
}
那么你会得到更简单的:
@FXML
private TableColumn<MyObject, SelectableInfo> myObjectChoicesTableColumn ;
myObjectChoicesTableColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue().getSelectableInfo());
myObjectChoicesTableColumn.setCellFactory(col -> {
ComboBox<SomeInfo> combo = new ComboBox<>();
TableCell<MyObject, SelectableInfo> cell = new TableCell<MyObject, SelectableInfo>() {
@Override
protected void updateItem(SelectableInfo info, boolean empty) {
super.updateItem(info, empty) ;
if (empty) {
setGraphic(null);
} else {
combo.setItems(info.getInfoList());
combo.setValue(info.getSelectedInfo());
setGraphic(combo);
}
}
};
combo.valueProperty().addListener((obs, oldValue, newValue) ->
cell.getItem().setSelectedInfo(newValue));
return cell ;
});
我的 table 视图有 2 列。第一个有我的对象的名称,第二个我想要一个 ComboBox,其值来自我的对象属性列表。
对 ComboBox 的任何更改都会将其 selected 属性更改为用户选择的列表元素。
例如:
| Name | Choices |
|---------------|-------------------|
| Object 1 Name | Object 1 ComboBox |
| Object 2 Name | Object 2 ComboBox |
到目前为止,我已经设法填充了名称,但我仍然停留在选择列中。
MyObject 模型:
public class MyObject {
// Objects name is the filename
private File file;
// Selection from the ComboBox that is populated with infoList elements
private SomeInfo selectedInfo;
private List<SomeInfo > infoList;
... getter/setter
控制器:
@FXML
private TableView<MyObject> myObjectTableView;
@FXML
private TableColumn<MyObject, String> myObjectNameTableColumn, myObjectChoicesTableColumn;
private void populateTableView(List<MyObject> myObjectList) {
ObservableList<MyObject> myObjectObservableList = FXCollections.observableList(myObjectList);
myObjectTableView.setItems(myObjectObservableList);
myObjectNameTableColumn.setCellValueFactory(c -> new SimpleStringProperty(c.getValue().getFile().getName()));
}
你的 myObjectChoicesTableColumn
类型有误。你需要
@FXML
private TableColumn<MyObject, List<SomeInfo>> myObjectChoicesTableColumn ;
那么你的cell value factory可以是
myObjectChoicesTableColumn.setCellValueFactory(cellData ->
new SimpleObjectProperty<>(cellData.getValue().getInfoList()));
要显示组合框,您需要一个单元工厂:
myObjectChoicesTableColumn.setCellFactory(col -> {
ComboBox<SomeInfo> combo ;
TableCell<MyObject, List<SomeInfo>> cell = new TableCell<MyObject, List<SomeInfo>>() {
@Override
protected void updateItem(List<SomeInfo> info, boolean empty) {
super.updateItem(info, empty);
if (empty) {
setGraphic(null);
} else {
MyObject rowItem = myObjectTableView.getItems().get(getIndex());
combo.getItems().setAll(info);
combo.setValue(rowItem.getSelectedInfo());
setGraphic(combo);
}
}
};
combo.valueProperty().addListener((obs, oldValue, newValue) ->
myObjectTableView.getItems().get(cell.getIndex()).setSelectedInfo(newValue));
return cell ;
}
您可能会发现重构模型更清晰,因此您可以将列表和所选项目包装在新的 class:
public class SelectableInfo {
private final ObservableList<SomeInfo> infoList = FXCollections.observableArrayList() ;
private SomeInfo selectedInfo ;
public ObservableList<SomeInfo> getInfoList() {
return infoList ;
}
public SomeInfo getSelectedInfo() {
return selectedInfo ;
}
public void setSelectedInfo(SomeInfo info) {
selectedInfo = info ;
}
}
和
public class MyObject {
private File file ;
private SelectableInfo selectableInfo ;
// getters and setters...
}
那么你会得到更简单的:
@FXML
private TableColumn<MyObject, SelectableInfo> myObjectChoicesTableColumn ;
myObjectChoicesTableColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue().getSelectableInfo());
myObjectChoicesTableColumn.setCellFactory(col -> {
ComboBox<SomeInfo> combo = new ComboBox<>();
TableCell<MyObject, SelectableInfo> cell = new TableCell<MyObject, SelectableInfo>() {
@Override
protected void updateItem(SelectableInfo info, boolean empty) {
super.updateItem(info, empty) ;
if (empty) {
setGraphic(null);
} else {
combo.setItems(info.getInfoList());
combo.setValue(info.getSelectedInfo());
setGraphic(combo);
}
}
};
combo.valueProperty().addListener((obs, oldValue, newValue) ->
cell.getItem().setSelectedInfo(newValue));
return cell ;
});