gpt4 book ai didi

tableview - 在 JavaFX 8 中创建用于全选的框架类型列标题

转载 作者:行者123 更新时间:2023-12-02 23:07:35 25 4
gpt4 key购买 nike

我正在创建一个自定义 TableColumn,它是一个 CheckBox 控件,表示是否选择了该行。我们不想使用标准的 SHIFT 或 CONTROL + CLICK 来处理此问题,因为用户往往会无意中单击并失去选择。

我想做的是:

enter image description here

在这种情况下,列不应是基础数据模型的一部分,而仅表示选择或未选择的内容。它不应该以任何方式依赖于数据模型。如果用户选中列标题中的复选框,则应选择表中的所有记录(而不仅仅是可见的记录),如果取消选择,则应取消选择所有记录。

有没有办法以这种方式表示选择模型?

我遇到的第二个问题是,我的第一次尝试不会在 SceneBuilder 中显示为可选,因为(据我所知)TableColumn 不是节点,因此似乎在导入时被忽略?

任何帮助将不胜感激。

谢谢

最佳答案

一个可能的解决方案是扩展 TableViewSkin 以添加带有复选框的 TableColumn,虽然此列不是与用户的模型一起烘焙的,但对复选框选择的更改将影响表的选择模型。

虽然仅通过复选框进行选择工作正常,但您无法删除允许选择行的行为,因此您必须监听这两种情况。

此代码段有效,但尚未通过排序和修改模型进行测试,因此它只是自定义 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;
}
}

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();
}
}

现在是示例,带有 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();

}

对于通常的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
}

CheckTableView

此自定义控件也可与场景生成器一起使用。

关于tableview - 在 JavaFX 8 中创建用于全选的框架类型列标题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37334094/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com