JavaFXTableView使用复选框填充列表

JavaFXTableView使用复选框填充列表,java,checkbox,javafx,tableview,Java,Checkbox,Javafx,Tableview,我对JavaFX相当陌生,我正试图在JavaFX中实现这一原则:我有一个用Student对象填充的TableView。我希望第一列是一个复选框,通过它我可以选择每一行对所选项目执行批量操作(如邮件应用程序示例中常见的) 我想我不应该向Student类添加SimpleBoleAnProperty,因为它只在视图层中使用,这就是为什么我认为我可以这样实现它:选中复选框时,学生将被添加到selectedStudents列表中;如果未选中,则会将其删除。这是一个好方法吗 这是我到目前为止得到的代码(主要

我对JavaFX相当陌生,我正试图在JavaFX中实现这一原则:我有一个用Student对象填充的TableView。我希望第一列是一个复选框,通过它我可以选择每一行对所选项目执行批量操作(如邮件应用程序示例中常见的)

我想我不应该向Student类添加SimpleBoleAnProperty,因为它只在视图层中使用,这就是为什么我认为我可以这样实现它:选中复选框时,学生将被添加到selectedStudents列表中;如果未选中,则会将其删除。这是一个好方法吗

这是我到目前为止得到的代码(主要基于类似解决方案的复制粘贴):

voornaamKolom.setCellValueFactory(新属性值工厂(“名称”);
familienaamKolom.setCellValueFactory(新的PropertyValueFactory(“fname”));
promotorKolom.setCellValueFactory(新的PropertyValueFactory(“注释”));
selectedKolom.setCellValueFactory(
新回调函数(){
@凌驾
公共observeValue调用(TableColumn.celldatap){
返回新的SimpleBoleAnProperty(p.getValue()!=null);
}
});
selectedKolom.setCellFactory(
新回调函数(){
@凌驾
公共TableCell调用(TableP列){
返回新的CheckBoxCell(studentantabel);
}
});
studentabel.getItems().setAll(getModel().getStudenten());
--

私有类CheckBoxCell扩展了TableCell{
最终复选框cellCheckBox=新复选框();
CheckBoxCell(最终表格视图tblView){
setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent t){
int-selectedIndex=getTableRow().getIndex();
如果(!cellCheckBox.isSelected()){
getModel().selectStudent(selectedIndex);//添加到selectedStudents
}否则{
getModel().取消选择学生(selectedIndex);//从selectedStudents中删除
}
}
});
}
//如果行不为空,则显示按钮
@凌驾
受保护的void updateItem(布尔值t,布尔值为空){
super.updateItem(t,空);
如果(!空){
设置图形(cellCheckBox);
}
}
}
此代码的主要问题是复选框未绑定到表行。例如,当我选择第二个项目并通过对另一个值排序来更改行顺序时,第二个项目仍然被选中,即使它代表另一个对象。当向表中添加新行时,其中一些行也会被随机选择

我知道这段代码可能相当脏,就像我说的:我对JavaFX是新手。任何帮助都将不胜感激


提前谢谢

您可以实现
getModel()
getModel()。取消选择学生(selectedObject)取而代之。在这里,
selectedObject
应该是对象本身,而不仅仅是索引。模型应该指向对象,而不是索引


最好记住,可以使模型指向所创建的确切对象。您只需确保指向了正确的对象。

您可以实现
getModel()
getModel()。取消选择学生(selectedObject)取而代之。在这里,
selectedObject
应该是对象本身,而不仅仅是索引。模型应该指向对象,而不是索引


最好记住,可以使模型指向所创建的确切对象。您只需确保指向了正确的对象。

您可以实现
getModel()
getModel()。取消选择学生(selectedObject)取而代之。在这里,
selectedObject
应该是对象本身,而不仅仅是索引。模型应该指向对象,而不是索引


最好记住,可以使模型指向所创建的确切对象。您只需确保指向了正确的对象。

您可以实现
getModel()
getModel()。取消选择学生(selectedObject)取而代之。在这里,
selectedObject
应该是对象本身,而不仅仅是索引。模型应该指向对象,而不是索引


最好记住,可以使模型指向所创建的确切对象。您只需确保指向正确的对象。

在我看来,您的复选框列的数据类型应该是
Student
;i、 它是一个
表格列
。这样做的原因是,您实际上是在展示整个对象本身的视图:学生包含在所选学生的集合中。有点违反直觉,但它让它起作用

看看这个例子是否有用。我没有将数据很好地分离到代码所暗示的模型中,但是您也应该能够考虑到这一点

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class SelectableTable extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> itemTable = new TableView<>();
        for (int i=1; i<=40; i++) {
            itemTable.getItems().add(new Item("Item "+i));
        }
        TableColumn<Item, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));


        TableColumn<Item, Item> selectedCol = new TableColumn<>("Select");

        // Collection of items currently selected via checkboxes in the table 
        // This will be passed to the TableCell implementation.
        ObservableSet<Item> selectedItems = FXCollections.observableSet();

        selectedCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Item,Item>, ObservableValue<Item>>() {

            @Override
            public ObservableValue<Item> call(CellDataFeatures<Item, Item> data) {
                return new ReadOnlyObjectWrapper<>(data.getValue());
            }
        });

        selectedCol.setCellFactory(new Callback<TableColumn<Item, Item>, TableCell<Item, Item>>() {

            @Override
            public TableCell<Item, Item> call(
                    TableColumn<Item, Item> param) {
                return new CheckBoxCell(selectedItems);
            }
        });

        itemTable.getColumns().addAll(selectedCol, nameCol);

        Button displayButton = new Button("Display selected");
        displayButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                for (Item item : selectedItems) {
                    System.out.println(item.getName());
                }
            }
        });

        Button selectAllButton = new Button("Select all");
        selectAllButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                selectedItems.addAll(itemTable.getItems());
            }
        });

        Button selectNoneButton = new Button("Select none");
        selectNoneButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                selectedItems.clear();
            }
        });

        HBox buttons = new HBox(5);
        buttons.getChildren().addAll(selectAllButton, selectNoneButton, displayButton);

        BorderPane root = new BorderPane();
        root.setCenter(itemTable);
        root.setBottom(buttons);

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static class CheckBoxCell extends TableCell<Item, Item> {

        private final ObservableSet<Item> selectedItems ;
        private final CheckBox checkBox ;

        public CheckBoxCell(ObservableSet<Item> selectedItems) {
            this.selectedItems = selectedItems ;
            this.checkBox = new CheckBox() ;


            // listener to update the set of selected items when the 
            // check box is checked or unchecked:
            checkBox.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    if (checkBox.isSelected()) {
                        selectedItems.add(getItem());
                    } else {
                        selectedItems.remove(getItem());
                    }
                }
            });

            // listener to update the check box when the collection of selected
            // items changes:
            selectedItems.addListener(new SetChangeListener<Item>() {

                @Override
                public void onChanged(Change<? extends Item> change) {
                    Item item = getItem();
                    if (item != null) {
                        checkBox.setSelected(selectedItems.contains(item));
                    }
                }

            });
        }

        @Override
        public void updateItem(Item item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
            } else {
                checkBox.setSelected(selectedItems.contains(item));
                setGraphic(checkBox);
            }
        }
    }

    public static class Item {
        private final StringProperty name = new SimpleStringProperty(this, "name");
        public StringProperty nameProperty() {
            return name ;
        }
        public final String getName() {
            return name.get();
        }
        public final void setName(String name) {
            this.name.set(name);
        }
        public Item(String name) {
            setName(name);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
导入javafx.application.application;
导入javafx.beans.property.ReadOnlyObjectWrapper;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.beans.value.observeValue;
导入javafx.collections.FXCollections;
导入javafx.collections.observeSet;
导入javafx.collections.SetChangeListener;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.CheckBox;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.control.TableColumn
private class CheckBoxCell extends TableCell<Student, Boolean> {

    final CheckBox cellCheckBox = new CheckBox();

    CheckBoxCell(final TableView tblView) {

        cellCheckBox.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                int selectedIndex = getTableRow().getIndex();

                if (!cellCheckBox.isSelected()) {
                    getModel().selectStudent(selectedIndex); // add to selectedStudents
                } else {
                    getModel().deselectStudent(selectedIndex); // remove from selectedStudents
                }
            }
        });
    }

    //Display button if the row is not empty
    @Override
    protected void updateItem(Boolean t, boolean empty) {
        super.updateItem(t, empty);
        if (!empty) {
            setGraphic(cellCheckBox);
        }
    }
}
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class SelectableTable extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> itemTable = new TableView<>();
        for (int i=1; i<=40; i++) {
            itemTable.getItems().add(new Item("Item "+i));
        }
        TableColumn<Item, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));


        TableColumn<Item, Item> selectedCol = new TableColumn<>("Select");

        // Collection of items currently selected via checkboxes in the table 
        // This will be passed to the TableCell implementation.
        ObservableSet<Item> selectedItems = FXCollections.observableSet();

        selectedCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Item,Item>, ObservableValue<Item>>() {

            @Override
            public ObservableValue<Item> call(CellDataFeatures<Item, Item> data) {
                return new ReadOnlyObjectWrapper<>(data.getValue());
            }
        });

        selectedCol.setCellFactory(new Callback<TableColumn<Item, Item>, TableCell<Item, Item>>() {

            @Override
            public TableCell<Item, Item> call(
                    TableColumn<Item, Item> param) {
                return new CheckBoxCell(selectedItems);
            }
        });

        itemTable.getColumns().addAll(selectedCol, nameCol);

        Button displayButton = new Button("Display selected");
        displayButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                for (Item item : selectedItems) {
                    System.out.println(item.getName());
                }
            }
        });

        Button selectAllButton = new Button("Select all");
        selectAllButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                selectedItems.addAll(itemTable.getItems());
            }
        });

        Button selectNoneButton = new Button("Select none");
        selectNoneButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                selectedItems.clear();
            }
        });

        HBox buttons = new HBox(5);
        buttons.getChildren().addAll(selectAllButton, selectNoneButton, displayButton);

        BorderPane root = new BorderPane();
        root.setCenter(itemTable);
        root.setBottom(buttons);

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static class CheckBoxCell extends TableCell<Item, Item> {

        private final ObservableSet<Item> selectedItems ;
        private final CheckBox checkBox ;

        public CheckBoxCell(ObservableSet<Item> selectedItems) {
            this.selectedItems = selectedItems ;
            this.checkBox = new CheckBox() ;


            // listener to update the set of selected items when the 
            // check box is checked or unchecked:
            checkBox.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    if (checkBox.isSelected()) {
                        selectedItems.add(getItem());
                    } else {
                        selectedItems.remove(getItem());
                    }
                }
            });

            // listener to update the check box when the collection of selected
            // items changes:
            selectedItems.addListener(new SetChangeListener<Item>() {

                @Override
                public void onChanged(Change<? extends Item> change) {
                    Item item = getItem();
                    if (item != null) {
                        checkBox.setSelected(selectedItems.contains(item));
                    }
                }

            });
        }

        @Override
        public void updateItem(Item item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
            } else {
                checkBox.setSelected(selectedItems.contains(item));
                setGraphic(checkBox);
            }
        }
    }

    public static class Item {
        private final StringProperty name = new SimpleStringProperty(this, "name");
        public StringProperty nameProperty() {
            return name ;
        }
        public final String getName() {
            return name.get();
        }
        public final void setName(String name) {
            this.name.set(name);
        }
        public Item(String name) {
            setName(name);
        }
    }

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