在JavaFX的表格中获取复选框值

我有一个表,它有一个复选框的行。

我想要做的是在按钮点击我想找出什么复选框被选中,哪些不是。 到目前为止,我设法在表中创建复选框。 代码如下。

到目前为止的输出

public class TTEs implements Initializable{ @FXML private TableView<TestObject> tableReport; @FXML private TableColumn<TestObject, String> name; @FXML private TableColumn<TestObject, Boolean> checkbox; @FXML public void getValues(){ //the method will get what check boxes are checked (this part is the problem) } @Override public void initialize(URL arg0, ResourceBundle arg1) { ObservableList<TestObject> data = FXCollections.observableArrayList(); data.add(new TestObject("Test 1", true)); data.add(new TestObject("Test 2", false)); tableReport.setItems(data); name.setCellValueFactory(new PropertyValueFactory<TestObject, String>("name")); checkbox.setCellValueFactory(new PropertyValueFactory<TestObject, Boolean>("checked")); checkbox.setCellFactory(new Callback<TableColumn<TestObject, Boolean>, TableCell<TestObject, Boolean>>() { public TableCell<TestObject, Boolean> call(TableColumn<TestObject, Boolean> p) { return new CheckBoxTableCell<TestObject, Boolean>(); } }); } //CheckBoxTableCell for creating a CheckBox in a table cell public static class CheckBoxTableCell<S, T> extends TableCell<S, T> { private final CheckBox checkBox; private ObservableValue<T> ov; public CheckBoxTableCell() { this.checkBox = new CheckBox(); this.checkBox.setAlignment(Pos.CENTER); setAlignment(Pos.CENTER); setGraphic(checkBox); } @Override public void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { setGraphic(checkBox); if (ov instanceof BooleanProperty) { checkBox.selectedProperty().unbindBidirectional((BooleanProperty) ov); } ov = getTableColumn().getCellObservableValue(getIndex()); if (ov instanceof BooleanProperty) { checkBox.selectedProperty().bindBidirectional((BooleanProperty) ov); } } } } 

}

当我调试时,我发现,

  ov = getTableColumn().getCellObservableValue(getIndex()); if (ov instanceof BooleanProperty) { checkBox.selectedProperty().bindBidirectional((BooleanProperty) ov); } 

在上述的情况下,如果没有进入。 意思是ovis i = nota实例如果是布尔属性。 但是当我打印ov的类时,

 System.out.println(ov.getClass().getName()); 

它打印为

javafx.beans.property.ReadOnlyObjectWrapper

ReadOnlyObjectWrapperBooleanProperty的一个子类

在Java 8上测试
只有4件简单的事情。

1)制作CheckBoxCellFactory类。 放在你的项目的某个地方。

 public class CheckBoxCellFactory implements Callback { @Override public TableCell call(Object param) { CheckBoxTableCell<Person,Boolean> checkBoxCell = new CheckBoxTableCell(); return checkBoxCell; } } 

2)你的模型类。 比如人。

 public static class Person { private SimpleBooleanProperty checked = new SimpleBooleanProperty(false); // other columns here public SimpleBooleanProperty checkedProperty() { return this.checked; } public java.lang.Boolean getChecked() { return this.checkedProperty().get(); } public void setChecked(final java.lang.Boolean checked) { this.checkedProperty().set(checked); } // getter/setter for other columns } 

3)在你的fxml文件中进行修改。 你的TableView – > TableColumn的部分会看起来像这样:

 <TableColumn fx:id="checkBoxTableColumn" maxWidth="34.0" minWidth="26.0" prefWidth="34.0" resizable="false" sortable="false"> <cellValueFactory><PropertyValueFactory property="checked" /></cellValueFactory> <cellFactory><partarch.fx.CheckBoxCellFactory /></cellFactory> </TableColumn> 

4)如果你想让你的复选框是可编辑的

  • 4.1在场景构建器中打开fxml。
  • 4.2选择checkBox列,然后在“属性”窗格中选中“可编辑”属性。
  • 4.3选择包含您的复选框的TableView,并执行相同的操作(在“属性”窗格中选中“可编辑”属性)。

GitHub的 SF和源文件中执行二进制文件

循环遍历TableView的数据模型,检查绑定到每个CheckBox的布尔值。

 @FXML public void getValues(){ ObservableList<TestObject> data = tableReport.getItems(); for (TestObject item : data){ //check the boolean value of each item to determine checkbox state } } 
 package checkboxtablecelltest; import javafx.application.Application; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.stage.Stage; /** * * @author reegan */ public class CheckBoxTableCellTest extends Application { @Override public void start(Stage primaryStage) { final TableView<Person> tableView = new TableView<Person>(); tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); tableView.setItems(FXCollections.observableArrayList( new Person("Robert", "Plant"), new Person("Neil", "Young"), new Person("Willie", "Nelson"), new Person("Natalie", "Merchant"))); tableView.getItems().get(3).setVegetarian(true); final TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name"); final TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name"); final TableColumn<Person, Boolean> vegetarianCol = new TableColumn<Person, Boolean>("Vegetarian"); tableView.getColumns().addAll(firstNameCol, lastNameCol, vegetarianCol); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); vegetarianCol.setCellValueFactory(new PropertyValueFactory<Person, Boolean>("vegetarian")); vegetarianCol.setCellFactory(CheckBoxTableCell.forTableColumn(vegetarianCol)); vegetarianCol.setEditable(true); tableView.setEditable(true); final BorderPane root = new BorderPane(); root.setCenter(tableView); final HBox controls = new HBox(5); final Button infoButton = new Button("Show details"); infoButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { for (Person p : tableView.getItems()) { System.out.printf("%s %s (%svegetarian)%n", p.getFirstName(), p.getLastName(), p.isVegetarian() ? "" : "not "); System.out.println(tableView.getSelectionModel().getSelectedItems()); } System.out.println(); } }); controls.getChildren().add(infoButton); root.setBottom(controls); Scene scene = new Scene(root, 300, 400); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } public static class Person { private StringProperty firstName; private StringProperty lastName; private BooleanProperty vegetarian; public Person(String firstName, String lastName) { this.firstName = new SimpleStringProperty(firstName); this.lastName = new SimpleStringProperty(lastName); this.vegetarian = new SimpleBooleanProperty(false); } public String getFirstName() { return firstName.get(); } public String getLastName() { return lastName.get(); } public boolean isVegetarian() { return vegetarian.get(); } public void setFirstName(String firstName) { this.firstName.set(firstName); } public void setLastName(String lastName) { this.lastName.set(lastName); } public void setVegetarian(boolean vegetarian) { this.vegetarian.set(vegetarian); } public StringProperty firstNameProperty() { return firstName; } public StringProperty lastNameProperty() { return lastName; } public BooleanProperty vegetarianProperty() { return vegetarian; } } } 

`

你的方法的主要问题是CheckBoxTableCell用法:Cell是一个重复使用的“渲染”机器。 如果你试图添加一个状态,比如CheckBox变量,你就麻烦了。

对您的问题最简单的解决办法是每次分配复选框。 以下代码提供了一个工作复选框列:

 public static class Member { private StringProperty myName; private BooleanProperty myCheck; public Member(String name, boolean checked) { myName = new SimpleStringProperty(name); myCheck = new SimpleBooleanProperty(checked); } public StringProperty nameProperty() { return myName; } public BooleanProperty checkProperty() { return myCheck; } } VBox testTable6(VBox box) { // check box bind to cell property ObservableList<Member> members = FXCollections.observableArrayList(); members.add(new Member("peter", true)); members.add(new Member("gernot", true)); members.add(new Member("fritz", false)); TableView<Member> table = new TableView<Member>(); table.prefHeightProperty().bind(box.heightProperty()); table.setItems(members); TableColumn<Member,String> c1 = new TableColumn<Member,String>("Name"); c1.setCellValueFactory(new PropertyValueFactory<Member,String>("name")); table.getColumns().add(c1); TableColumn<Member,Boolean> c2 = new TableColumn<Member,Boolean>("Membercheck"); c2.setCellValueFactory(new PropertyValueFactory<Member,Boolean>("check")); c2.setCellFactory(column -> new TableCell<Member, Boolean>(){ public void updateItem(Boolean check, boolean empty) { super.updateItem(check, empty); if (check == null || empty) { setGraphic(null); } else { CheckBox box = new CheckBox(); BooleanProperty checked = (BooleanProperty)column.getCellObservableValue(getIndex()); box.setSelected(checked.get()); box.selectedProperty().bindBidirectional(checked); setGraphic(box); } } } ); table.getColumns().add(c2); box.getChildren().addAll(table); return box; } 

由于双向属性绑定是一个弱绑定,即使您无法明确解绑,carbage集合也能正常工作。

无论如何,在这里,未经检查的转换为BooleanProperty并不是一个好的样式,对不起。 考虑使用以下命令访问整个对象:

 ... Member member = table.getItems().get(getIndex()); box.setSelected(member.checkProperty().get()); box.selectedProperty().bindBidirectional(member.checkProperty()); .... 

顺便说一句:双向绑定不会在那一刻设置选定的属性,只有当它被改变后! 所以明确的任务:

 box.setSelected(member.checkProperty().get()); 

这里是强制性的。

一个小题目 – 但在Kotlin你可以这样做:

  isPvtColumn.cellFactory = Callback { CheckBoxTableCell<KeyWithProperties, Boolean>() } isPvtColumn.cellValueFactory = Callback { a -> a.value.private } 

这就是它的全部

在初始化方法中,切换JavaFX提供的自定义工厂:

 @Override public void initialize(URL arg0, ResourceBundle arg1) { ObservableList<TestObject> data = FXCollections.observableArrayList(); data.add(new TestObject("Test 1", true)); data.add(new TestObject("Test 2", false)); tableReport.setItems(data); name.setCellValueFactory(new PropertyValueFactory<TestObject, String>("name")); checkbox.setCellValueFactory(new PropertyValueFactory<TestObject, Boolean>("checked")); checkbox.setCellFactory( CheckBoxTableCell.forTableColumn(checkbox) ); } 

现在你的数据绑定到列,你可以遍历项目,并检查“检查”字段:

 @FXML public void getValues(){ ObservableList<TestObject> data = tableReport.getItems(); for (TestObject item : data){ //check the boolean value of each item to determine checkbox state } }