JavaFX 中的 TableView 和 Spinner
TableView and Spinner in JavaFX
我可以在 table 单元格中设置微调器。
但问题是我在使用 getSelectionModel() 时无法获得此值。
有什么方法可以做到这一点?
我目前使用的代码是这样的:
QuantitaCol.setCellValueFactory(new PropertyValueFactory<Strumento, Integer>("Quantita_Disp"));
QuantitaCol.setCellFactory(new Callback<TableColumn<Strumento,Integer>,TableCell<Strumento,Integer>>(){
@Override
public TableCell<Strumento, Integer> call(TableColumn<Strumento, Integer> param) {
TableCell<Strumento, Integer> cell = new TableCell<Strumento, Integer>(){
@Override
public void updateItem(Integer item, boolean empty) {
if(item!=null){
Spinner<Integer> quantita = new Spinner<Integer>(0, item, 1);
quantita.valueProperty().addListener(
(obs, oldValue, newValue) -> {
System.out.println("New value: "+item);
}
);
setGraphic(quantita);
}
}
};
return cell;
}
});
试试这个替代代码,而不是使用 updateItem() 和 setGraphic() 函数
TableColumn<Strumento, Spinner> SpinnerCol = new TableColumn<Strumento, Spinner>("Quantity");
SpinnerCol.setMinWidth(500);
SpinnerCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Strumento, Spinner>, ObservableValue<Spinner>>() {
@Override
public ObservableValue<Spinner> call(
TableColumn.CellDataFeatures<Strumento, Spinner> arg0) {
Strumento strumentoObject = arg0.getValue();
Spinner<Integer> quantita = new Spinner<Integer>(0, 10, 1);
quantita.valueProperty().addListener(
(obs, oldValue, newValue) -> {
System.out.println("New value: " + newValue);
strumentoObject.setSpinnerValue(newValue);
}
);
return new SimpleObjectProperty<Spinner>(quantita);
}
});
table.getColumns().add(SpinnerCol);
已编辑
虽然此解决方案可以快速解决您的问题,但我强烈建议您遵循以下评论中专家推荐的 解决方案。
您创建了 Spinner
并设置了值,但是您永远不会将值写回您的项目。为此
a) 您的项目 class 需要包含微调器的最大值和当前值(或者仅包含当前值,如果每个项目的最大值都相同)
b) 列的 ObservableValue
需要包含最大值和当前值的数据。
以下示例仅使用 table 项目本身作为列的值:
public static class Item {
private final IntegerProperty itemCount = new SimpleIntegerProperty();
private final IntegerProperty itemMaxCount = new SimpleIntegerProperty();
@Override
public String toString() {
return Integer.toString(getItemCount());
}
public Item(int disp, int max) {
this.itemCount.setValue(disp);
this.itemMaxCount.setValue(max);
}
public final int getItemCount() {
return this.itemCount.get();
}
public final void setItemCount(int value) {
this.itemCount.set(value);
}
public final IntegerProperty itemCountProperty() {
return this.itemCount;
}
public final int getItemMaxCount() {
return this.itemMaxCount.get();
}
public final void setItemMaxCount(int value) {
this.itemMaxCount.set(value);
}
public final IntegerProperty itemMaxCountProperty() {
return this.itemMaxCount;
}
}
@Override
public void start(Stage primaryStage) {
TableView<Item> tv = new TableView<>(FXCollections.observableArrayList(
new Item(1, 10),
new Item(0, 9),
new Item(1, 8),
new Item(0, 7),
new Item(1, 42),
new Item(0, 4),
new Item(1, 2),
new Item(0, 99),
new Item(1, 77),
new Item(0, 44),
new Item(1, 11),
new Item(0, 2),
new Item(1, 2),
new Item(0, 3),
new Item(1, 5),
new Item(0, 6)
));
TableColumn<Item, Item> countColumn = new TableColumn<>("count");
countColumn.setCellValueFactory(cd -> Bindings.createObjectBinding(() -> cd.getValue()));
countColumn.setCellFactory(new Callback<TableColumn<Item, Item>, TableCell<Item, Item>>() {
@Override
public TableCell<Item, Item> call(TableColumn<Item, Item> param) {
TableCell<Item, Item> cell = new TableCell<Item, Item>() {
private final Spinner<Integer> count;
private final SpinnerValueFactory.IntegerSpinnerValueFactory valueFactory;
private final ChangeListener<Number> valueChangeListener;
{
valueFactory = new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 0);
count = new Spinner<>(valueFactory);
count.setVisible(false);
setGraphic(count);
valueChangeListener = (ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
valueFactory.setValue(newValue.intValue());
};
count.valueProperty().addListener((obs, oldValue, newValue) -> {
if (getItem() != null) {
// write new value to table item
getItem().setItemCount(newValue);
}
});
}
@Override
public void updateItem(Item item, boolean empty) {
// unbind old values
valueFactory.maxProperty().unbind();
if (getItem() != null) {
getItem().itemCountProperty().removeListener(valueChangeListener);
}
super.updateItem(item, empty);
// update according to new item
if (empty || item == null) {
count.setVisible(false);
} else {
valueFactory.maxProperty().bind(item.itemMaxCountProperty());
valueFactory.setValue(item.getItemCount());
item.itemCountProperty().addListener(valueChangeListener);
count.setVisible(true);
}
}
};
return cell;
}
});
tv.getColumns().add(countColumn);
Button btn = new Button("Print");
btn.setOnAction((ActionEvent event) -> {
System.out.println(tv.getItems());
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(new VBox(10, tv, btn));
primaryStage.setScene(scene);
primaryStage.show();
}
我可以在 table 单元格中设置微调器。
但问题是我在使用 getSelectionModel() 时无法获得此值。
有什么方法可以做到这一点?
我目前使用的代码是这样的:
QuantitaCol.setCellValueFactory(new PropertyValueFactory<Strumento, Integer>("Quantita_Disp"));
QuantitaCol.setCellFactory(new Callback<TableColumn<Strumento,Integer>,TableCell<Strumento,Integer>>(){
@Override
public TableCell<Strumento, Integer> call(TableColumn<Strumento, Integer> param) {
TableCell<Strumento, Integer> cell = new TableCell<Strumento, Integer>(){
@Override
public void updateItem(Integer item, boolean empty) {
if(item!=null){
Spinner<Integer> quantita = new Spinner<Integer>(0, item, 1);
quantita.valueProperty().addListener(
(obs, oldValue, newValue) -> {
System.out.println("New value: "+item);
}
);
setGraphic(quantita);
}
}
};
return cell;
}
});
试试这个替代代码,而不是使用 updateItem() 和 setGraphic() 函数
TableColumn<Strumento, Spinner> SpinnerCol = new TableColumn<Strumento, Spinner>("Quantity");
SpinnerCol.setMinWidth(500);
SpinnerCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Strumento, Spinner>, ObservableValue<Spinner>>() {
@Override
public ObservableValue<Spinner> call(
TableColumn.CellDataFeatures<Strumento, Spinner> arg0) {
Strumento strumentoObject = arg0.getValue();
Spinner<Integer> quantita = new Spinner<Integer>(0, 10, 1);
quantita.valueProperty().addListener(
(obs, oldValue, newValue) -> {
System.out.println("New value: " + newValue);
strumentoObject.setSpinnerValue(newValue);
}
);
return new SimpleObjectProperty<Spinner>(quantita);
}
});
table.getColumns().add(SpinnerCol);
已编辑
虽然此解决方案可以快速解决您的问题,但我强烈建议您遵循以下评论中专家推荐的
您创建了 Spinner
并设置了值,但是您永远不会将值写回您的项目。为此
a) 您的项目 class 需要包含微调器的最大值和当前值(或者仅包含当前值,如果每个项目的最大值都相同)
b) 列的 ObservableValue
需要包含最大值和当前值的数据。
以下示例仅使用 table 项目本身作为列的值:
public static class Item {
private final IntegerProperty itemCount = new SimpleIntegerProperty();
private final IntegerProperty itemMaxCount = new SimpleIntegerProperty();
@Override
public String toString() {
return Integer.toString(getItemCount());
}
public Item(int disp, int max) {
this.itemCount.setValue(disp);
this.itemMaxCount.setValue(max);
}
public final int getItemCount() {
return this.itemCount.get();
}
public final void setItemCount(int value) {
this.itemCount.set(value);
}
public final IntegerProperty itemCountProperty() {
return this.itemCount;
}
public final int getItemMaxCount() {
return this.itemMaxCount.get();
}
public final void setItemMaxCount(int value) {
this.itemMaxCount.set(value);
}
public final IntegerProperty itemMaxCountProperty() {
return this.itemMaxCount;
}
}
@Override
public void start(Stage primaryStage) {
TableView<Item> tv = new TableView<>(FXCollections.observableArrayList(
new Item(1, 10),
new Item(0, 9),
new Item(1, 8),
new Item(0, 7),
new Item(1, 42),
new Item(0, 4),
new Item(1, 2),
new Item(0, 99),
new Item(1, 77),
new Item(0, 44),
new Item(1, 11),
new Item(0, 2),
new Item(1, 2),
new Item(0, 3),
new Item(1, 5),
new Item(0, 6)
));
TableColumn<Item, Item> countColumn = new TableColumn<>("count");
countColumn.setCellValueFactory(cd -> Bindings.createObjectBinding(() -> cd.getValue()));
countColumn.setCellFactory(new Callback<TableColumn<Item, Item>, TableCell<Item, Item>>() {
@Override
public TableCell<Item, Item> call(TableColumn<Item, Item> param) {
TableCell<Item, Item> cell = new TableCell<Item, Item>() {
private final Spinner<Integer> count;
private final SpinnerValueFactory.IntegerSpinnerValueFactory valueFactory;
private final ChangeListener<Number> valueChangeListener;
{
valueFactory = new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 0);
count = new Spinner<>(valueFactory);
count.setVisible(false);
setGraphic(count);
valueChangeListener = (ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
valueFactory.setValue(newValue.intValue());
};
count.valueProperty().addListener((obs, oldValue, newValue) -> {
if (getItem() != null) {
// write new value to table item
getItem().setItemCount(newValue);
}
});
}
@Override
public void updateItem(Item item, boolean empty) {
// unbind old values
valueFactory.maxProperty().unbind();
if (getItem() != null) {
getItem().itemCountProperty().removeListener(valueChangeListener);
}
super.updateItem(item, empty);
// update according to new item
if (empty || item == null) {
count.setVisible(false);
} else {
valueFactory.maxProperty().bind(item.itemMaxCountProperty());
valueFactory.setValue(item.getItemCount());
item.itemCountProperty().addListener(valueChangeListener);
count.setVisible(true);
}
}
};
return cell;
}
});
tv.getColumns().add(countColumn);
Button btn = new Button("Print");
btn.setOnAction((ActionEvent event) -> {
System.out.println(tv.getItems());
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(new VBox(10, tv, btn));
primaryStage.setScene(scene);
primaryStage.show();
}