pur*_*eon 3 tableview tablecolumn javafx-8
我正在寻找创建一个自定义TableColumn,这是一个CheckBox控件,表示是否选择了该行。我们不希望使用标准的SHIFT或CONTROL + CLICK来处理此问题,因为用户倾向于无意间单击并丢失选择。
我想做的是以下几点:
在这种情况下,该列不应成为基础数据模型的一部分,而应仅代表选择或不选择的内容。它不应该以任何方式依赖于数据模型。如果用户选中列标题中的复选框,则应选择表中的所有记录(而不仅是可见记录),如果取消选择,则应取消选择所有记录。
有没有办法以这种方式表示选择模型?
我遇到的第二个问题是,我的第一次尝试将不会在SceneBuilder中显示为可选择项,因为(从我的收集中可以看出)TableColumn不是Node,因此似乎在导入时被忽略了吗?
任何帮助将不胜感激。
谢谢
可能的解决方案可能是扩展TableViewSkin以添加TableColumn带有复选框的,而此列并未随用户模型一起提供,但是复选框选择的更改将影响表的选择模型。
虽然仅通过复选框进行选择可以很好地工作,但是您无法删除允许选择行的行为,因此您必须侦听这两种情况。
该代码段有效,但是尚未经过对模型进行排序和修改的测试,因此,这只是custom的一个开始TableView。
CheckTableView类
public class CheckTableView<T> extends TableView<T> {
private ObservableList<T> selected;
public CheckTableView() {
this(FXCollections.observableArrayList());
}
public CheckTableView(ObservableList<T> items) {
setItems(items);
setEditable(true);
getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
skinProperty().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
selected = ((CheckTableViewSkin) getSkin()).getSelectedRows();
skinProperty().removeListener(this);
}
});
}
@Override
protected Skin<?> createDefaultSkin() {
return new CheckTableViewSkin<>(this);
}
public ObservableList<T> getSelectedRows() {
return selected;
}
}
Run Code Online (Sandbox Code Playgroud)
CheckTableViewSkin类
public class CheckTableViewSkin<T> extends TableViewSkin<T> {
private final TableColumn<T, Boolean> checkColumn;
private final CheckBox headerCheckBox = new CheckBox();
private final List<BooleanProperty> colSelected = new ArrayList<>();
private final ChangeListener<Number> listener = (obs, ov, nv) -> {
if (nv.intValue() != -1) {
Platform.runLater(() -> {
colSelected.get(nv.intValue()).set(!colSelected.get(nv.intValue()).get());
refreshSelection();
});
}
};
private final ChangeListener<Boolean> headerListener = (obs, ov, nv) -> {
Platform.runLater(() -> {
IntStream.range(0, colSelected.size()).forEach(i -> colSelected.get(i).set(nv));
refreshSelection();
});
};
public CheckTableViewSkin(CheckTableView<T> control) {
super(control);
checkColumn = new TableColumn<>();
headerCheckBox.selectedProperty().addListener(headerListener);
checkColumn.setGraphic(headerCheckBox);
// install listeners in checkboxes
IntStream.range(0, control.getItems().size()).forEach(i -> {
final SimpleBooleanProperty simple = new SimpleBooleanProperty();
simple.addListener((obs, ov, nv) -> refreshSelection());
colSelected.add(simple);
});
checkColumn.setCellFactory(CheckBoxTableCell.forTableColumn(colSelected::get));
checkColumn.setPrefWidth(60);
checkColumn.setEditable(true);
checkColumn.setResizable(false);
getColumns().add(0, checkColumn);
getSelectionModel().selectedIndexProperty().addListener(listener);
}
private void refreshSelection() {
// refresh list of selected rows
getSelectionModel().selectedIndexProperty().removeListener(listener);
getSelectionModel().clearSelection();
AtomicInteger count = new AtomicInteger();
IntStream.range(0, colSelected.size()).forEach(i -> {
if (colSelected.get(i).get()) {
getSelectionModel().select(i);
count.getAndIncrement();
}
});
headerCheckBox.selectedProperty().removeListener(headerListener);
headerCheckBox.setSelected(count.get() == colSelected.size());
headerCheckBox.selectedProperty().addListener(headerListener);
// it may flick, but required to show all selected rows focused
getSkinnable().requestFocus();
getSelectionModel().selectedIndexProperty().addListener(listener);
}
public ObservableList<T> getSelectedRows() {
return getSelectionModel().getSelectedItems();
}
}
Run Code Online (Sandbox Code Playgroud)
现在是带有Application类的示例:
@Override
public void start(Stage primaryStage) {
TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");
firstNameColumn.setCellValueFactory(p -> p.getValue().firstNameProperty());
TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setCellValueFactory(p -> p.getValue().lastNameProperty());
CheckTableView<Person> tableView = new CheckTableView(FXCollections.observableArrayList(
new Person("Hans", "Muster"), new Person("Ruth", "Mueller"),
new Person("Heinz", "Kurz"), new Person("Cornelia", "Meier"),
new Person("Anna", "Best"), new Person("Stefan", "Meier")
));
tableView.getColumns().addAll(firstNameColumn, lastNameColumn);
Scene scene = new Scene(tableView, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
Run Code Online (Sandbox Code Playgroud)
对于普通Person班:
public class Person {
private final StringProperty firstName;
private final StringProperty lastName;
public Person(String firstName, String lastName) {
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
}
//getters & setters
}
Run Code Online (Sandbox Code Playgroud)
此自定义控件也将与Scene Builder一起使用。
| 归档时间: |
|
| 查看次数: |
1479 次 |
| 最近记录: |