Malek Boubakri
Malek Boubakri

Reputation: 856

JavaFX: TableView row selection

I am working on a java/Javafx project for the first time and i have a TableView with multiple column (name, prename, age...) to present my data and I need the user to be able to select a single row and give me everytime all anformation about the person(Other columns) even when he click at another column but I haven't been able to find the right way to do it. When i select a row my code give everytime the value of the cell i click on, but i need other informations to search with in my SQLite data base and work on it (Delete/edit this person..)

Here is the code that i use:

...//rest of code

@Override
public void initialize(URL location, ResourceBundle resources) {

private TableView<Student> tbl_elev=new TableView<Student>();

...

tbl_elev.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
            @Override
            public void changed(ObservableValue<?> observableValue, Object oldValue, Object newValue) {
                //Check whether item is selected and set value of selected item to Label
                if (tbl_elev.getSelectionModel().getSelectedItem() != null) {
                    TableViewSelectionModel<Student> selectionModel = tbl_elev.getSelectionModel();
                    ObservableList<?> selectedCells = selectionModel.getSelectedCells();
                    @SuppressWarnings("unchecked")
                    TablePosition<Object, ?> tablePosition = (TablePosition<Object, ?>) selectedCells.get(0);
                    Object val = tablePosition.getTableColumn().getCellData(newValue);
                    System.out.println("Selected Value " + val);
                }
            }
            });
}

... //rest of code

I am waiting for your suggestions and ideas, i dont mind if you suggest another approach because this may be uncompatible (taken from internet) Please if you need any other part of the code just comment, i don't put it all because it is too long to read.. (Sorry of my bad english)

Upvotes: 0

Views: 8979

Answers (2)

Malek Boubakri
Malek Boubakri

Reputation: 856

After too many failed attempts and thanks to @Jonatan 's answer the code after i compelete some missing words should be like this:

...//rest of code

@Override
public void initialize(URL location, ResourceBundle resources) {

private TableView<Student> tbl_elev=new TableView<Student>();

...

        tbl_elev.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Student>() {
              // Here's the key part. See how I specify that the
              // parameters are of type student. Now you can use the
              // instance methods from Student.
              @Override
              public void changed(ObservableValue<? extends Student> observable,Student oldValue, Student newValue){
                  if(newValue!=null){
                        System.out.println(newValue.getName() + " "+ newValue.getPrename()+" "+newValue.getNaiss());
                  }
              //you can add any other value from Student class via getter(getAdr,getMail,...)

              }
          });
}

... //rest of code

Output example:

Jonatan stenbacka 2015-09-11

Those value are ready for use to fetch the data base and specify the needed row in it to work on. Hope that this help someone one day. thanks...

Upvotes: 0

Jonatan Stenbacka
Jonatan Stenbacka

Reputation: 1864

If you specify that the ChangeListener parameters are of type Student you can get use the instance methods from that object:

Here's a Minimal, Complete, and Verifiable example:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class SSCCE extends Application {

    @Override
    public void start(Stage stage) {

        VBox root = new VBox();

        TableView<Student> studentsTable = new TableView<Student>();

        HBox studentBox = new HBox();
        Label studentHeader = new Label("Student: ");
        Label studentInfo = new Label("");
        studentBox.getChildren().addAll(studentHeader, studentInfo);

        root.getChildren().addAll(studentsTable, studentBox);

        // Prepare the columns
        TableColumn<Student, String> firstNameCol = new TableColumn<Student, String>(
                "First name");
        firstNameCol.setCellValueFactory(cellData -> cellData.getValue()
                .firstNameProperty());

        TableColumn<Student, String> lastNameCol = new TableColumn<Student, String>(
                "Last name");
        lastNameCol.setCellValueFactory(cellData -> cellData.getValue()
                .lastNameProperty());

        studentsTable.getSelectionModel().selectedItemProperty()
                .addListener(new ChangeListener<Student>() {

                    // Here's the key part. See how I specify that the
                    // parameters are of type student. Now you can use the
                    // instance methods from Student.
                    @Override
                    public void changed(
                            ObservableValue<? extends Student> observable,
                            Student oldValue, Student newValue ) {

                        studentInfo.setText(newValue.getFirstName() + " "
                                + newValue.getLastName());
                        // If you want to get the value of a selected student cell at
                        // anytime, even if it hasn't changed. Just do e.g.
                        // studentsTable.getSelectionModel().getSelectedItem().getFirstName()
                    }
                });

        studentsTable.getColumns().setAll(firstNameCol, lastNameCol);

        // Some mock Student objects
        Student student1 = new Student("Eric", "Smith");
        Student student2 = new Student("Brad", "Jones");
        Student student3 = new Student("Logan", "Thorpe");

        // Fill the table with students.
        studentsTable.getItems().addAll(student1, student2, student3);

        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    // The student class. In this case an inner class to simplify the example. But generally you should never use inner classes.
    class Student {

        private StringProperty firstName;
        private StringProperty lastName;

        public Student(String firstName, String lastName) {
            this.firstName = new SimpleStringProperty(firstName);
            this.lastName = new SimpleStringProperty(lastName);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String firstName) {
            this.firstName.set(firstName);
        }

        public StringProperty firstNameProperty() {
            return firstName;
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String lastName) {
            this.lastName.set(lastName);
        }

        public StringProperty lastNameProperty() {
            return lastName;
        }
    }

}

Upvotes: 5

Related Questions