import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ListChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;

import java.util.List;

public class TableSelectionIssue extends Application {

    TableView<Person> tableView;

    @Override
    public void start(Stage stage) {
        tableView = new TableView<>();
        tableView.getSelectionModel().setCellSelectionEnabled(true);
        tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        var c1 = createCol("First Name", "firstName");
        var c2 = createCol("Last Name", "lastName");

        tableView.getColumns().addAll(List.of(c1, c2));

        var ab = new Person();
        ab.setFirstName("a");
        ab.setLastName("b");
        tableView.getItems().add(ab);

        var cd = new Person();
        cd.setFirstName("c");
        cd.setLastName("d");
        tableView.getItems().add(cd);

        final Scene scene = new Scene(tableView, 600, 400);
        stage.setScene(scene);
        stage.show();

        tableView.getSelectionModel().getSelectedItems().addListener((ListChangeListener<Person>) change ->
                System.out.println("Change: " + change + ",  selected items: " + tableView.getSelectionModel().getSelectedItems()));
    }

    private TableColumn<Person, String> createCol(String name, String propertyName) {
        var tableColumn = new TableColumn<Person, String>(name);
        tableColumn.setCellValueFactory(new PropertyValueFactory<>(propertyName));
        return tableColumn;
    }

    public static class Person {
        private StringProperty firstName;
        public void setFirstName(String value) { firstNameProperty().set(value); }
        public String getFirstName() { return firstNameProperty().get(); }
        public StringProperty firstNameProperty() {
            if (firstName == null) firstName = new SimpleStringProperty(this, "firstName");
            return firstName;
        }

        private StringProperty lastName;
        public void setLastName(String value) { lastNameProperty().set(value); }
        public String getLastName() { return lastNameProperty().get(); }
        public StringProperty lastNameProperty() {
            if (lastName == null) lastName = new SimpleStringProperty(this, "lastName");
            return lastName;
        }

        @Override
        public String toString() {
            return "Person{" +
                    firstName.get() +
                    " " + lastName.get() +
                    '}';
        }
    }
}