Get Checkbox value in table in JavaFX

I have a table and it has a row with a checkbox.

What I want to do is click on the button "I want to know which checkboxes are checked and which ones are not." So far I have managed to create checkboxes in the table. The code is as follows.

The output so far

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

}

when i debug i found that

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

in the above agreement, it never goes inside if. Means ovis instance i = nota if Boolean matters. But when I print the ov class,

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

he prints like

javafx.beans.property.ReadOnlyObjectWrapper

ReadOnlyObjectWrapper is a subclass of BooleanProperty

+6
source share
6 answers

Tested in Java 8.
Only 4 simple things.

1) Make a class CheckBoxCellFactory. Put somewhere in your project.

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

2) Model class. For example, a person.

 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) Made changes to the fxml file. The section of your TableView -> TableColumn will look like this:

 <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) If you want to make your checkbox editable

  • 4.1 Open fxml in the scene builder.
  • 4.2 Select the checkBox column, and then select the Editable property in the Properties panel.
  • 4.3 Select the TableView containing your checkbox and do the same (check the "Editable" property in the "Properties" panel).

SF binary implementation and source on github

+12
source

Scroll through the data model of your TableView , checking the boolean value that is associated with each 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 } } 
+5
source
 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; } } } 

`

+4
source

The main problem with your approach is the use of CheckBoxTableCell: The cell is a heavily used rendering machine. If you try to add a state, such as a CheckBox variable, you have problems.

The simplest solution to the problem is to select the check box every time. The following code provides a working column for the flag:

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

Since a bidirectional property binding is weak binding, carbide assembly will work properly even if you cannot unbind explicitly.

An unverified cast on BooleanProperty is not a very good style, anyway, sorry. Think about accessing an entire object using:

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

By the way: birdeirectional binding will NOT set the selected property at this moment, only if it is changed later! therefore explicit purpose:

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

is a must here.

+2
source

A little off topic - but in Kotlin you can do this:

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

That's all there is in it

+1
source

In the initialize method, switch your own factory to the one provided by 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) ); } 

Now your data is bound to a column, and you can iterate over the elements and check the "checked" field:

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

All Articles