I'm a newbie in JavaFX and I have no idea how to solve this problem. So, I have a checkbox column in a TableView. For example, I select 3 first boxes and scroll down the table. But when I go to the top of table, checkboxes are not selected. Here is some code:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.util.LinkedList;
import java.util.List;
public class App extends Application
{
List<User> list = new LinkedList<>();
TableColumn<User, Integer> id;
TableColumn<User, String> firstName;
TableColumn<User, Boolean> selected;
TableView<User> tableView;
public static void main(String[] args)
{
launch();
}
@Override
public void start(Stage stage) throws Exception
{
stage.setHeight(500);
stage.setWidth(500);
stage.setMinHeight(200);
stage.setMinHeight(100);
stage.setTitle("Table view");
tableView = new TableView<>();
ObservableList<User> list = FXCollections.observableArrayList();
for(int i = 0; i < 40; i++)
{
list.add(new User(i, "first name", "last name"));
}
id = new TableColumn("ID");
id.setCellValueFactory(new PropertyValueFactory<User, Integer>("id"));
firstName = new TableColumn("First Name");
firstName.setCellValueFactory(new PropertyValueFactory<User, String>("firstName"));
TableColumn<User, String> lastName = new TableColumn("Last Name");
lastName.setCellValueFactory(new PropertyValueFactory<User, String>("lastName"));
selected = new TableColumn("Select");
Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>> booleanCellFactory = new Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>>()
{
@Override
public TableCell<User, Boolean> call(TableColumn<User, Boolean> p)
{
return new CheckBoxCell();
}
};
selected.setCellValueFactory(new PropertyValueFactory<User, Boolean>("active"));
selected.setCellFactory(booleanCellFactory);
tableView.getColumns().addAll(id, firstName, lastName, selected);
tableView.setItems(list);
BorderPane pane = new BorderPane();
pane.setCenter(tableView);
Scene scene = new Scene(pane);
stage.setScene(scene);
stage.show();
}
class CheckBoxCell extends TableCell<User, Boolean>
{
private CheckBox checkbox;
@Override
protected void updateItem(Boolean item, boolean empty)
{
super.updateItem(item, empty);
checkbox = new CheckBox();
checkbox.setAlignment(Pos.CENTER);
setAlignment(Pos.CENTER);
setGraphic(checkbox);
checkbox.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent actionEvent)
{
if(!checkbox.isSelected())
{
list.remove(tableView.getItems().get(getTableRow().getIndex()));
} else
{
list.add(tableView.getItems().get(getTableRow().getIndex()));
}
System.out.println(list);
}
});
}
}
}
And the data class "User":
public class User
{
private int id;
private String firstName;
private String lastName;
User(int id, String firstName, String lastName)
{
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
}
In your code for Table Column "slected"
selected.setCellValueFactory(new PropertyValueFactory<User, Boolean>("active"));
you're setting propertyvalue factory "active" but there is no "active" property in your User class .When you move scroll bar tableview trigger updateItem method,as you don't have active property (even if you have property default value is false) checkbox.setSelected(item); line will deselect checkbox as item value is always false.
To fix this issue define a BooleanProperty active in user class and update property value when user selected/deselected checkbox.
Here is whole code which is working
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.scene.layout.BorderPane;
import java.util.LinkedList;
import java.util.List;
public class TestApp extends Application {
List<User> list = new LinkedList<>();
TableColumn<User, Integer> id;
TableColumn<User, String> firstName;
TableColumn<User, Boolean> selected;
TableView<User> tableView;
public static void main(String[] args)
{
launch();
}
@Override
public void start(Stage stage) throws Exception
{
stage.setHeight(500);
stage.setWidth(500);
stage.setMinHeight(200);
stage.setMinHeight(100);
stage.setTitle("Table view");
tableView = new TableView<>();
ObservableList<User> list = FXCollections.observableArrayList();
for(int i = 0; i < 40; i++)
{
list.add(new User(i, "first name", "last name"));
}
id = new TableColumn("ID");
id.setCellValueFactory(new PropertyValueFactory<User, Integer>("id"));
firstName = new TableColumn("First Name");
firstName.setCellValueFactory(new PropertyValueFactory<User, String>("firstName"));
TableColumn<User, String> lastName = new TableColumn("Last Name");
lastName.setCellValueFactory(new PropertyValueFactory<User, String>("lastName"));
selected = new TableColumn("Select");
Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>> booleanCellFactory = new Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>>()
{
@Override
public TableCell<User, Boolean> call(TableColumn<User, Boolean> p)
{
return new CheckBoxCell();
}
};
selected.setCellValueFactory(new PropertyValueFactory<User, Boolean>("active"));
selected.setCellFactory(booleanCellFactory);
tableView.getColumns().addAll(id, firstName, lastName, selected);
tableView.setItems(list);
BorderPane pane = new BorderPane();
pane.setCenter(tableView);
Scene scene = new Scene(pane);
stage.setScene(scene);
stage.show();
}
class CheckBoxCell extends TableCell<User, Boolean>
{
private CheckBox checkbox = new CheckBox();
public CheckBoxCell(){
checkbox.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent actionEvent)
{
if(!checkbox.isSelected())
{
list.remove(tableView.getItems().get(getTableRow().getIndex()));
User user = getTableView().getItems().get(getTableRow().getIndex());
user.setActive(false);
} else
{
list.add(tableView.getItems().get(getTableRow().getIndex()));
User user = getTableView().getItems().get(getTableRow().getIndex());
user.setActive(true);
}
System.out.println(list);
}
});
}
@Override
protected void updateItem(Boolean item, boolean empty)
{
super.updateItem(item, empty);
if(!empty && item != null) {
checkbox.setAlignment(Pos.CENTER);
checkbox.setSelected(item);
setAlignment(Pos.CENTER);
setGraphic(checkbox);
}
}
}
User Class :
public class User
{
private IntegerProperty id;
private StringProperty firstName;
private StringProperty lastName;
private BooleanProperty active;
User(int id, String firstName, String lastName)
{
this.id = new SimpleIntegerProperty(id);
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
this.active = new SimpleBooleanProperty(false);
}
public int getId() {
return id.get();
}
public IntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getFirstName() {
return firstName.get();
}
public StringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public StringProperty lastNameProperty() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public boolean getActive() {
return active.get();
}
public BooleanProperty activeProperty() {
return active;
}
public void setActive(boolean active) {
this.active.set(active);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With