0

I am just trying to see if I am able to get data from MS Access into a table using a TableView in FXML, but none of the data from my table in MS Access appears in the TableView. However, if I display just the content of my table as a message dialogue, all the correct information appears. Please can someone show me where I am going wrong.

I watched this Youtube video 1, and followed it step by step, as well as other sources, but nothing fixes my issue.


    @FXML
    private TableView<modelTable> table;
    @FXML
    private TableColumn<modelTable, StringProperty> colStudentName;
    @FXML
    private TableColumn<modelTable, StringProperty> colSurname;
    @FXML
    private TableColumn<modelTable, IntegerProperty> colGrade;
    @FXML
    private TableColumn<modelTable, StringProperty> colEmail;

    ObservableList<modelTable> list = FXCollections.observableArrayList();

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        try {
            Connection connection = DBConnect.getConnection();
            ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM data");

            while (rs.next()) {
//If I run the JOptionPane on its own, all the data is displayed
                //JOptionPane.showMessageDialog(null, (rs.getString("StudentName")+ "\t" + rs.getString("Surname") + "\t" + rs.getInt("Grade") + "\t" + rs.getString("Email")));
                list.add(new modelTable(rs.getString("StudentName"), rs.getString("Surname"), rs.getInt("Grade"), rs.getString("Email")));
            }
        } catch (SQLException ex) {
            Logger.getLogger(TableController.class.getName()).log(Level.SEVERE, null, ex);
        }

        colStudentName.setCellValueFactory(new PropertyValueFactory<>("StudentName"));
        colSurname.setCellValueFactory(new PropertyValueFactory<>("Surname"));
        colGrade.setCellValueFactory(new PropertyValueFactory<>("Grade"));
        colEmail.setCellValueFactory(new PropertyValueFactory<>("Email"));

        table.setItems(list);
    }

}
public class modelTable {

    private StringProperty colName, colSurname, colEmail;
    private IntegerProperty colGrade;

    public modelTable(String colName, String colSurname, int colGrade, String colEmail) {
        this.colName = new SimpleStringProperty(colName);
        this.colSurname = new SimpleStringProperty(colSurname);
        this.colEmail = new SimpleStringProperty(colEmail);
        this.colGrade = new SimpleIntegerProperty(colGrade);
    }

    public String getColName() {
        return colName.get();
    }

    public void setColName(String colName) {
        this.colName.set(colName);
    }

    public String getColSurname() {
        return colSurname.get();
    }

    public void setColSurname(String colSurname) {
        this.colSurname.set(colSurname);
    }

    public String getColEmail() {
        return colEmail.get();
    }

    public void setColEmail(String colEmail) {
        this.colEmail.set(colEmail);
    }

    public int getColGrade() {
        return colGrade.get();
    }

    public void setColGrade(int colGrade) {
        this.colGrade.set(colGrade);
    }

}
public class DBConnect {

    public static Connection getConnection() throws SQLException{
        Connection connection = DriverManager.getConnection("jdbc:ucanaccess://C://Users//Huzaifah//Desktop//School work 2019//testing table.accdb");
        return connection;
    }

I expect the data to be in the TableView when I run the program, but it's empty. No error message is given, only an empty table.

I tried using this same database in just a simple program without a TableView and it works perfectly fine.

Huzaifah
  • 43
  • 3

1 Answers1

0

The problem is with your how you're setting your CellValueFactory for each column:

colStudentName.setCellValueFactory(new PropertyValueFactory<>("StudentName"));
colSurname.setCellValueFactory(new PropertyValueFactory<>("Surname"));
colGrade.setCellValueFactory(new PropertyValueFactory<>("Grade"));
colEmail.setCellValueFactory(new PropertyValueFactory<>("Email"));

The properties you're specifying (StudentName, Surname, etc) do not match any exposed properties in your modelTable class. In modelTable, all your properties begin with "col" for some reason.

As a side note, Java naming conventions suggest that class names begin with a capital letter...


You should refactor your ModelTable class to use properties that are visible by your TableView. You should change your property names to be more reflective of the data. Adding a "col" prefix is confusing and unnecessary as your model class should not care or be aware of how it is going to be displayed:

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

class Scratch {

    private final StringProperty name = new SimpleStringProperty();
    private final StringProperty surname = new SimpleStringProperty();
    private final StringProperty email = new SimpleStringProperty();
    private final IntegerProperty grade = new SimpleIntegerProperty();

    public modelTable(String colName, String colSurname, int colGrade, String colEmail) {
        this.name.set(colName);
        this.surname.set(colSurname);
        this.email.set(colEmail);
        this.grade.set(colGrade);
    }

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

    public StringProperty nameProperty() {
        return name;
    }

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

    public String getSurname() {
        return surname.get();
    }

    public StringProperty surnameProperty() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname.set(surname);
    }

    public String getEmail() {
        return email.get();
    }

    public StringProperty emailProperty() {
        return email;
    }

    public void setEmail(String email) {
        this.email.set(email);
    }

    public int getGrade() {
        return grade.get();
    }

    public IntegerProperty gradeProperty() {
        return grade;
    }

    public void setGrade(int grade) {
        this.grade.set(grade);
    }
}

Note how we now declare the properties as final and initialize them as class fields. We can do this because we may change the value of a property, but will not change the property itself.

Also notice that we are adding a getter for each property. This allows us to refer to them directly in the controller when setting each CellValueFactory.

Then you need to update your setCellValueFactory() methods to use the new property names. I do not recommend using reflection (creating a new PropertyValueFactory(), however), as with your exposed properties, that is not necessary.

Instead, just pass a reference to the properties directly:

colStudentName.setCellValueFactory(features -> features.getValue().nameProperty());
colSurname.setCellValueFactory(features -> features.getValue().surnameProperty());
colEmail.setCellValueFactory(features -> features.getValue().emailProperty());
colGrade.setCellValueFactory(features -> features.getValue().gradeProperty());
Zephyr
  • 9,885
  • 4
  • 28
  • 63
  • Please can you clear this for me (I'm still a school going student), which properties in the code links to the TableView and which properties link to the column names in my MS Access table. – Huzaifah Apr 25 '19 at 13:57
  • I recommend reading up on the MCV pattern in JavaFX. The column names in your Access database are not relevant to your `TableView`. Once you load the data from your database into the `ModelTable` objects, you will use those properties for the `TableView`. – Zephyr Apr 25 '19 at 14:00