JavaFX: Populating TableView with models from different classes
Asked Answered
E

1

1

I know there are 20 threads about this, but nothing really has worked for me.

I have 2 models which I want to populate the tableView from.

One is Student with a surname, name and stuff.

The second one is called Termin (date in English probably). It has a two dimensional list that is called Awlist where we store times of a student that came to late at a specific day. We do this because we're using ORMlite and it won't really work different with something else.

I want 4 columns of student and 1 column that gives me the time the student was too late at that day. But I really can't fix it with my group.

How it is right now:

idColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("id"));
vornameColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("vn"));
nachnameColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("nn"));
matrikelnummerColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("matnr"));
gruppeColumn.setCellValueFactory(cellData -> {
    if (cellData.getValue() == null)
        return new SimpleStringProperty("");
    else
        return new SimpleStringProperty(cellData.getValue().getGroup().getBezeichnung());
});
fehlzeitColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("fehlZeit"));

tableView.setItems(getTableViewList());</code>

This thing called "fehlZeit" is the time the student was too late.

I don't show all the List methods that call it. It's just a problem to implement it right. I know it should be like this then and getColumns().addAll instead of setItems() am I right?

fehlzeitColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("fehlZeit"));
Enterogastrone answered 7/1, 2019 at 23:56 Comment(1)
Not really sure what you're asking, but if you want to display data from 2 different model classes, you'll need a "wrapper" class for the TableView instead; something that contains the fields you want from both models.Sealy
S
4

Your question is not clear on how you retrieve your data from the database or why you cannot combine the data in your queries, so I will demonstrate how to use multiple object models to populate your TableView.

The TableView can only display items of one type, so you cannot simply combine different objects into a single TableView. The way around this is to create a wrapper class that holds the data you want from both objects.

The example below will demonstrate one way to do this. There are three class: Student, Times, and DisplayStudent. Both Student and Time objects would come from your database.

We then build a list of DisplayStudent objects, combining both the Student and the Times, based on matching StudentId properties.

We can then display our list of DisplayStudent objects in the TableView.


import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TableViewMultiModel extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // *** CREATE OUR SAMPLE DATA (these two lists would come from your database)
        ObservableList<Student> students = FXCollections.observableArrayList();
        ObservableList<Times> times = FXCollections.observableArrayList();

        // This is our list of DisplayStudents that combines all our data into one model for the TableView
        ObservableList<DisplayStudent> displayStudents = FXCollections.observableArrayList();

        // *** Now populate our lists (again, would be filled from your database
        students.addAll(
                new Student(1, "Jack"),
                new Student(2, "Breane")
        );
        times.addAll(
                new Times(1, "14:42"),
                new Times(2, "4:00"),
                new Times(1, "1:23"),
                new Times(1, "2:20"),
                new Times(2, "1:03")
        );

        // *** Now, we need to combine the items from the two lists into DisplayStudent objects which will be shown
        // *** in our TableView. Normally, you'd be doing this with SQL queries, but that depends on your database.
        for (Times time :
                times) {
            // For each Times, we want to retrieve the corresponding Student from the students list. We'll use the
            // Java 8 Streams API to do this
            students.stream()
                    // Check if the students list contains a Student with this ID
                    .filter(p -> p.getStudentId() == time.getStudentId())
                    .findFirst()
                    // Add the new DisplayStudent to the list
                    .ifPresent(s -> {
                        displayStudents.add(new DisplayStudent(
                                s,
                                time
                        ));
                    });
        }

        // *** Now that our model is in order, let's create our TableView
        TableView<DisplayStudent> tableView = new TableView<>();
        TableColumn<DisplayStudent, String> colName = new TableColumn<>("Name");
        TableColumn<DisplayStudent, String> colTime = new TableColumn<>("Late Minutes");

        colName.setCellValueFactory(f -> f.getValue().getStudent().nameProperty());
        colTime.setCellValueFactory(f -> f.getValue().getTimes().timeProperty());

        tableView.getColumns().addAll(colName, colTime);
        tableView.setItems(displayStudents);

        root.getChildren().add(tableView);

        // Show the Stage
        primaryStage.setWidth(300);
        primaryStage.setHeight(300);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

class Student {

    private final IntegerProperty studentId = new SimpleIntegerProperty();
    private final StringProperty name = new SimpleStringProperty();

    public Student(int id, String name) {
        this.studentId.setValue(id);
        this.name.set(name);
    }

    public int getStudentId() {
        return studentId.get();
    }

    public IntegerProperty studentIdProperty() {
        return studentId;
    }

    public void setStudentId(int studentId) {
        this.studentId.set(studentId);
    }

    public String getName() {
        return name.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }
}

class Times {

    private int studentId;
    private final StringProperty time = new SimpleStringProperty();

    public Times(int studentId, String time) {
        this.studentId = studentId;
        this.time.set(time);
    }

    public int getStudentId() {
        return studentId;
    }

    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }

    public String getTime() {
        return time.get();
    }

    public StringProperty timeProperty() {
        return time;
    }

    public void setTime(String time) {
        this.time.set(time);
    }
}

class DisplayStudent {
    private final ObjectProperty<Student> student = new SimpleObjectProperty<>();
    private final ObjectProperty<Times> times = new SimpleObjectProperty<>();

    public DisplayStudent(Student student, Times times) {
        this.student.set(student);
        this.times.set(times);
    }

    public Student getStudent() {
        return student.get();
    }

    public ObjectProperty<Student> studentProperty() {
        return student;
    }

    public void setStudent(Student student) {
        this.student.set(student);
    }

    public Times getTimes() {
        return times.get();
    }

    public ObjectProperty<Times> timesProperty() {
        return times;
    }

    public void setTimes(Times times) {
        this.times.set(times);
    }
}

The Result:

screenshot

Sealy answered 8/1, 2019 at 0:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.