java - 我可以在 TableView 中使用 CheckBoxTableCell 作为让用户选择多行的方法吗?

标签 java checkbox javafx tableview

在我的 TableView 中,我想要一个包含复选框的列。通过此复选框,用户可以选择要为特定操作(例如删除)标记哪些行。我尝试过使用 CheckBoxTableCell,但我看到的所有示例都已将复选框的值绑定(bind)到模型的某些 boolean 属性。我的TableView所基于的模型是JPA实体,并且没有这样的字段。我也不愿意添加这样的字段,因为除了用于此行选择目的之外,它与模型无关。

因此我的问题是,是否可以使用 CheckBoxTableCell 来选择多行。如果是这样,我该如何实现它并随后获取所选的每一行?如果没有,使用表列中的复选框实现多重选择的最佳方法是什么?

谢谢。

最佳答案

首先请注意,您只需使用 TableView 的默认选择实现即可实现此功能。 IE。调用table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 。然后用户可以选择多行,您可以只对选定的行进行操作。

如果您想使用复选框列来实现此功能,这并不太困难:

CheckBoxTableCell有一个 selectedStateCallback 属性,这是一个将单元格索引(即其行)映射到 ObservableValue<Boolean> 的函数。 。复选框的选定状态将绑定(bind)(如果可观察 boolean 值可写,则双向)到作为此函数结果的可观察 boolean 值的状态。

因此,正如您所见,通常您会将其映射到 BooleanProperty在模型对象中,但您可以将其映射到您喜欢的任何属性。如果您没有,您可以专门为此目的创建一个。

例如,您可能想要维护当前所选项目的某种集合:例如您可以使用 ObservableSet 。 (在下面的示例中,我假设表中没有重复的项目,即 .equals(...) 。如果您的表可能包含重复的行,则需要做更多的工作。)然后您只需将监听器注册到确保:

  1. 如果表示复选框选定状态的属性发生更改,您将更新选定项目的可观察集
  2. 如果可观察的所选项目集发生更改,您可以更新复选框(通过更新 boolean 属性)
  3. 如果重复使用该单元格来表示不同的项目,则需要更新该复选框。您可以使用单元格的 itemProperty 注册监听器为此目的。

这是一个示例,使用一个仅显示字符串的非常简单的表格。因为我们要从单元格的getItem中获取整行所代表的项方法中,我们使列的类型与表的类型相同(本例中为 String ,因此我们有 TableColumn<String, String> ),并使用 cellValueFactory包装整行的对象:selectedCol.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue())); 。在现实生活中,您的表类型可能会更复杂,并且可能会使用 ReadOnlyObjectWrapper<>(cellData.getValue());

import java.util.HashSet;

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener.Change;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TableViewSelectByCheckBox extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<String> table = createTable();

        TableColumn<String, String> selectedCol = new TableColumn<>();
        selectedCol.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue()));

        ObservableSet<String> selectedItems = FXCollections.observableSet(new HashSet<>());

        selectedCol.setCellFactory(col -> {

            // boolean property represents if the check box in the cell is selected:
            BooleanProperty selected = new SimpleBooleanProperty();
            // create check box cell and bind its state to property:
            CheckBoxTableCell<String, String> cell = new CheckBoxTableCell<>(index -> selected);

            // update set of selected indices if checkbox state changes:
            selected.addListener((obs, wasSelected, isNowSelected) -> {
                if (isNowSelected) {
                    selectedItems.add(cell.getItem());
                } else {
                    selectedItems.remove(cell.getItem());
                }
            });

            // update check box state if set of selected indices changes:
            selectedItems.addListener((Change<? extends String> change) -> {
                selected.set(cell.getItem() != null && selectedItems.contains(cell.getItem()));
            });

            // update check box when cell is reused for a different index:
            cell.itemProperty().addListener((obs, oldItem, newItem) -> {
                selected.set(newItem != null && selectedItems.contains(newItem));
            });

            return cell ;
        });

        table.getColumns().add(0, selectedCol);

        Button button = new Button("Show selected");
        button.setOnAction(e -> selectedItems.forEach(System.out::println));

        BorderPane.setAlignment(button, Pos.CENTER);
        BorderPane.setMargin(button, new Insets(5));


        BorderPane root = new BorderPane(table, null, null, button, null);
        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TableView<String> createTable() {
        TableView<String> table = new TableView<>();
        table.setEditable(true);
        TableColumn<String, String> itemCol = new TableColumn<>("Item");
        itemCol.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue()));
        table.getColumns().add(itemCol);
        for (int item = 1 ; item <= 100; item++) {
            table.getItems().add("Item "+item);
        }
        return table ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

关于java - 我可以在 TableView 中使用 CheckBoxTableCell 作为让用户选择多行的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34940563/

相关文章:

java - 检索 ArrayList 作为 session 属性

java - 在自定义过滤器java Play框架中获取请求正文

java - 监听器拒绝连接,并出现以下错误 : ORA-12519, TNS:未找到适当的服务处理程序

java - 检查是否所有复选框均已选中。安卓

java - 普通对象变量还是JavaFX对象属性?

java - 如何在 Scene Builder 中对齐所有文本字段?

java - 如何创建一个类来对java中的文件进行排序

javascript - 在下拉列表中单击复选框时,复选框保持选中状态

wpf - WPF 的自定义复选框样式

java - 使所有元素(包括 2 个 ListView )在 JavaFX 中一起滚动