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