【发布时间】:2015-06-15 12:18:47
【问题描述】:
我在SelectionMode.MULTIPLE 中有一个TableView。使用 ListChangeListener 我可以捕捉多行的选择(通过按 Shift)。
但是,我的解决方案只有在没有列的区域中的同一列或中选择项目时才有效。带有 4 个示例的 GIF 说明:
- 确定: 在 State 列中使用 Shift 选择 3 个项目
- 确定: 在 Idx 列中使用 Shift 选择 4 个项目
- 确定: 使用 Shift 从 State 列到无列区域选择 4 个项目
- 错误: 尝试使用 Shift 从 State 列到 Data Item 列选择 4 个项目
问题似乎是SelectedItems-list 在最后一个示例中显然是空的。非常感谢您在此问题上提供的帮助。
这是我的方法:
ObservableList<DataRowModel> dataRows = FXCollections.observableArrayList();
dataRows.addAll(dataSetModel.getRows());
tableDataRow.setItems(dataRows);
tableDataRowStateColumn.setCellValueFactory(f -> f.getValue().getState());
tableDataRow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
tableDataRow.getSelectionModel().getSelectedItems()
.addListener((ListChangeListener.Change<? extends DataRowModel> c) -> {
while (c.next()) {
c.getRemoved().stream().forEach(remitem -> remitem.setSelected(false));
c.getAddedSubList().stream().forEach(additem -> additem.setSelected(true));
System.out.println(c.getList()); //Empty [] when selected using different columns
}
});
只是为了更好地理解我的代码:setSelected(...) 在绑定到 State-Column 的 DataRowModel 上设置了一个 BooleanProperty。
如果没有上下文,使用这个选定属性的原因似乎很愚蠢。但是,还有各种其他代码片段,其中 ChangeListeners 绑定到 selected-property。
SSCCE 准备运行:
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class TableViewSample extends Application {
private TableView<DataRowModel> tableDataRow = new TableView<DataRowModel>();
private TableColumn<DataRowModel, String> tableDataRowNameColumn = new TableColumn<>("Data Item");
private TableColumn<DataRowModel, String> tableDataRowStateColumn = new TableColumn<>("State");
private final ObservableList<DataRowModel> dataRows =
FXCollections.observableArrayList(
new DataRowModel("Concinna", false),
new DataRowModel("Concinna", false),
new DataRowModel("Concinna", false),
new DataRowModel("Concinna", false),
new DataRowModel("Concinna", false)
);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(500);
stage.setHeight(500);
tableDataRow.setItems(dataRows);
tableDataRowNameColumn.setCellValueFactory(f -> f.getValue().getName());
tableDataRowStateColumn.setCellValueFactory(f -> f.getValue().getState());
tableDataRow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
tableDataRow.getSelectionModel().getSelectedItems()
.addListener((ListChangeListener.Change<? extends DataRowModel> c) -> {
while (c.next()) {
c.getRemoved().stream().forEach(remitem -> remitem.setSelected(false));
c.getAddedSubList().stream().forEach(additem -> additem.setSelected(true));
}
});
tableDataRow.getColumns().addAll(tableDataRowNameColumn, tableDataRowStateColumn);
((Group) scene.getRoot()).getChildren().addAll(tableDataRow);
stage.setScene(scene);
stage.show();
}
public static class DataRowModel {
private StringProperty name = new SimpleStringProperty(this, "name", "");
private BooleanProperty selected = new SimpleBooleanProperty(this, "selected", true);
private StringProperty state = new SimpleStringProperty(this, "state", "");
public DataRowModel(String name, boolean selected) {
this.name.setValue(name);
this.selected.setValue(selected);
this.selected.addListener((observable, oldVal, newVal) -> {
getState(); // Refresh State value
});
}
public StringProperty getName() {
return name;
}
public BooleanProperty isSelected() {
return selected;
}
public void setSelected(boolean selected) {
if (this.selected.getValue() != selected)
this.selected.setValue(selected);
}
public StringProperty getState() {
String stateStr = "";
if (selected.getValue())
stateStr += "Selected";
state.setValue(stateStr);
return state;
}
}
}
【问题讨论】:
-
虽然图像很好 - 最好是展示问题的 SSCCE :-)
-
已添加 - 删除了 SSCCE 中的一些不必要的内容,以尽可能精简 JavaFX 代码:)
-
我可以通过编辑 Oracle 的 Person tableview 示例来生成它。此错误提交为 bugs.openjdk.java.net/browse/JDK-8096787 ,并在 8u60 中修复。
-
谢谢!我刚刚安装了早期访问版本,它现在就像一个魅力。我刚刚查了官方发布日期(GA),应该是 2015 年 8 月
标签: java javafx java-8 javafx-8