Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix TableView when scrolling

Tags:

java

javafx

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

}
like image 551
hetsketch. Avatar asked Mar 12 '26 08:03

hetsketch.


1 Answers

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);
    }
}
like image 166
invariant Avatar answered Mar 13 '26 22:03

invariant