javafx tableView not showing data, something wrong with getter setters?
Asked Answered
S

1

-1

i am trying to populate data into my tableview everything seems fine but still it is not showing data. here is the code. everything seems to be fine but the tableview is not showing anything. not even blinking...



public class MainPage implements Initializable {
    
    
    

    @FXML
    private AnchorPane root;
    
      @FXML
        private Button main_LogOut;

        @FXML
        private ComboBox<?> main_Clients;

        @FXML
        private ComboBox<?> main_Users;

        @FXML
        private TableView<customerDetails> table;

        @FXML
        private TableColumn<customerDetails, String> clientId;
        

        @FXML
        private TableColumn<customerDetails, String> clientName;

        @FXML
        private TableColumn<customerDetails, String> clientEmail;

        @FXML
        private TableColumn<customerDetails, String> clientRequirement;

    
    @SuppressWarnings("unchecked")
    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        // TODO Auto-generated method stub
        clientId.setCellValueFactory(new PropertyValueFactory<customerDetails,String> ("Id"));
        clientName.setCellValueFactory(new PropertyValueFactory<customerDetails, String>("name"));
        clientEmail.setCellValueFactory(new PropertyValueFactory<customerDetails, String>("email"));
        clientRequirement.setCellValueFactory(new PropertyValueFactory<customerDetails, String>("Requirements"));
        table=new TableView<customerDetails>();
        table.setItems(getClients());
        table.getColumns().addAll(clientId,clientName,clientEmail,clientRequirement);
            
        
    }
    
    @FXML
    void loadScene(ActionEvent event) throws IOException
    {
        AnchorPane pane=FXMLLoader.load(getClass().getResource("/lists/MainPage.fxml"));
        root.getChildren().setAll(pane);
        
    }
    
    public ObservableList<customerDetails> getClients() 
    {
        
        ObservableList<customerDetails> cd=FXCollections.observableArrayList();
        customerDetails details=new customerDetails("moin123","moeen","789987","asdf","email","developer","abcd","adsadasdf","78987");
        cd.add(details);
        return cd;
        
        
    }

and the customers model..... i don't know if there is anything wrong with the getter setters. I have read some times there is issues with PropertyValueFactory. But here I would appreciate a little help.

public class customerDetails implements Serializable{
    private String Id;
    private String name;
    private String phone_Number;
    private String current_Address;
    private String job_Title;
    private String Company;
    private String Requirements;
    private String annual_Salary;
    private String email;
    
    public customerDetails()
    {
        
    }
    
    public customerDetails(String c_id, String Name, String number, String curr_Add, String j_Title, String company, String req, String salary,String e_mail)
    {
        this.Id=c_id;
        this.name=Name;
        this.phone_Number=number;
        this.current_Address=curr_Add;
        this.job_Title=j_Title;
        this.Company=company;
        this.Requirements=req;
        this.annual_Salary=salary;
        this.email=e_mail;
        
    }

    public String getId() {
        return Id;
    }

    public void setId(String id) {
        Id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getPhone_Number() {
        return phone_Number;
    }

    public void setPhone_Number(String phone_Number) {
        this.phone_Number = phone_Number;
    }

    public String getCurrent_Address() {
        return current_Address;
    }

    public void setCurrent_Address(String current_Address) {
        this.current_Address = current_Address;
    }

    public String getJob_Title() {
        return job_Title;
    }

    public void setJob_Title(String job_Title) {
        this.job_Title = job_Title;
    }

    public String getCompany() {
        return Company;
    }

    public void setCompany(String company) {
        Company = company;
    }

    public String getRequirements() {
        return Requirements;
    }

    public void setRequirements(String requirements) {
        Requirements = requirements;
    }

    public String getAnnual_Salary() {
        return annual_Salary;
    }

    public void setAnnual_Salary(String annual_Salary) {
        this.annual_Salary = annual_Salary;
    }

    public String getEmail() {
        return email;
    }

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

any idea what is wrong here?

Saguaro answered 19/1, 2021 at 5:13 Comment(4)
You need to follow naming conventions. That will probably fix your problems. I am not sure if it will but that's what's jumping out of the code.Tychon
plus: don't instanciate fields that are injectedPlumbic
instantiate fields?Saguaro
instantiate exactly, sry for the typo .. if you don't understand that comment, work through a tutorial on java language basics and one in how to use fxmlPlumbic
M
8

Don’t use PropertyValueFactory.

As you are seeing, it relies on reflection. This means you have to be very careful to specify the correct string, because the compiler cannot verify it for you.

A much better idea is to avoid reflection, so the compiler can verify that you have spelled everything correctly.

Have a look at the methods of the Node class. Notice how for every get-method, there is a corresponding method that returns the JavaFX property itself? It’s a pattern that is in most of the classes in JavaFX.

For instance, there are getBlendMode() and blendModeProperty() methods. getClip() and clipProperty() methods. getLayoutX() and layoutXProperty() methods.

Your data class needs to follow the same convention:

private final StringProperty idProperty = new SimpleStringProperty();
private final StringProperty nameProperty = new SimpleStringProperty();

public String getId() {
    return idProperty.get();
}

public void setId(String id) {
    idProperty.set(id);
}

public StringProperty idProperty() {
    return idProperty;
}

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

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

public StringProperty nameProperty() {
    return nameProperty;
}

// etc.

Why do this? Because now you can pass a property directly to the setCellValueFactory method of each column:

clientId.setCellValueFactory(f -> f.getValue().idProperty());
clientName.setCellValueFactory(f -> f.getValue().nameProperty());
// etc.

Notice that there are no " characters in the above code. Because actual methods are being used, the compiler can make sure you haven’t made any mistakes. (Avoiding reflection has other advantages, like performance.)

However… as Sedrick points out, this means your class will not be truly serializable. Attempting to write it to an ObjectOutputStream will result in a NotSerializableException, because JavaFX properties are not themselves serializable. It is not clear to me whether you actually intend to serialize customerDetails instances; if so, more work will be needed to make that possible.


As for what went wrong in your original code…

Creating a new TableView in code

When you load MainPage.fxml, your table field will be changed so it points to the TableView defined in that .fxml file. That is the TableView which you see in your window.

But then your code does this:

table=new TableView<customerDetails>();

By doing that, you have created a different TableView which is not visible in the window at all. You are setting the items of a TableView that no one ever sees.

Solution: remove the above line of code entirely.

Incorrect property names

The string passed to PropertyValueFactory must be a bean property name. A Java bean is also known as a POJO or Plain Old Java Object.

A bean property is defined by the Java Bean specification as a get-method. The name of the bean property is defined as the name of the get-method, without the get prefix, and the next letter in lowercase.

Since your customerDetails class has a getId method, the name of the corresponding bean property is id. Notice that once the ‘get’ is removed, the initial letter is in lowercase. This is critical. Bean properties are case sensitive.

When your code does new PropertyValueFactory<customerDetails,String>("Id"), you are passing a nonexistent property. The customerDetails class does not have a property named "Id", so the value factory can’t possibly return any data. The class does, however, have a property named "id". Case matters: "id" is correct, "Id" is incorrect.

The compiler compiles code, but doesn’t execute it. So the compiler doesn’t know that the string does not match the name of any bean property in customerDetails. This is why reflection is hazardous. It’s much safer and more robust to use code that the compiler can verify.

Mobocracy answered 19/1, 2021 at 6:0 Comment(4)
the OP is bound to run into a different issue using your idea. public class customerDetails implements Serializable.Tychon
that lower camelCase didn't work. I used the correct naming method as you said but still no result.....Saguaro
good explanation :) Only part of the problem here, though - the other part is that the table the OP is filling is not the table in the scenegraph ..Plumbic
@Plumbic Ah yes, that certainly is a fundamental problem. Answer updated. Also updated to address serialization as Sedrick rightly points out.Mobocracy

© 2022 - 2024 — McMap. All rights reserved.