Javafx tableview not showing data in all columns

keithmhome picture keithmhome · Sep 24, 2013 · Viewed 27.9k times · Source

OK, new to java by several weeks, but have been programming for 30 years. The following code executes, but only the first column is showing anything. The data object is showing multiple rows of data, with fields of data that are filled in. I'm sure I'm missing something, and have looked through similar questions on here.

APVoucher_batchgridController.java

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;

/**
 * FXML Controller class
 *
 * @author kmitchell
 */
public class APVoucher_batchgridController implements Initializable {

    public TableView tblMainList;
    public TableColumn colDateEntered;
    public TableColumn colCreatedBy;
    public TableColumn colDescription;

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }

    @FXML
    public void opentables(ActionEvent event) {

        Object forName = null;
        Connection conn = null;
        Statement stmt = null;

        ResultSet rs = null;

        colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("DateEntered"));

        colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("cDesc"));

        colCreatedBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("CreatedBy"));

        try {
            // load the driver into memory
            forName = Class.forName("jstels.jdbc.dbf.DBFDriver2");

        } catch (ClassNotFoundException ex) {
            Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            conn = DriverManager.getConnection("jdbc:jstels:dbf:e:\\keystone-data\\keyfund\\seymour\\keyfund.dbc");
        } catch (SQLException ex) {
            Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
        }

        if (conn != null) {
            try {
                stmt = conn.createStatement();
            } catch (SQLException ex) {
                Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
            }

            if (stmt != null) {

                // execute a query
                try {
                    ObservableList<Object> data = FXCollections.observableArrayList();

                    rs = stmt.executeQuery("SELECT denteredon, cdesc, ccreatedby FROM apvbatch WHERE ldeleted = false ORDER BY denteredon DESC");

                    while (rs.next()) {

                        String enteredon = rs.getString("denteredon");
                        String desc = rs.getString("cdesc");
                        String createdby = rs.getString("ccreatedby");

                        sresult row = new sresult(createdby, enteredon, desc);

                        data.add(row);
                    }

                    tblMainList.setItems(data);

                    tblMainList.setVisible(true);


                } catch (SQLException ex) {
                    Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    public class sresult {

        private String DateEntered;
        private String EnteredBy;
        private String cDesc;

        public sresult(String T, String d, String c) {
            this.EnteredBy = T;
            this.DateEntered = d;
            this.cDesc = c;
        }

        public String getEnteredBy() {
            return EnteredBy;
        }

        public void setEnteredBy(String T) {
            EnteredBy = T;
        }

        public String getDateEntered() {
            return DateEntered;
        }

        public void setDateEntered(String d) {
            DateEntered = d;
        }

        public String getcDesc() {
            return cDesc;
        }

        public void setcDesc(String c) {
            cDesc = c;
        }
    }
}

and APVoucher_batchgrid.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<AnchorPane id="AnchorPane" fx:id="batchlistform" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="keystone.APVoucher_batchgridController">
  <children>
    <BorderPane layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
      <center>
        <AnchorPane prefHeight="-1.0" prefWidth="-1.0">
          <children>
            <Pane layoutX="0.0" layoutY="0.0" prefHeight="53.0" prefWidth="580.0">
              <children>
                <Label layoutX="7.0" layoutY="9.0" prefWidth="202.0" text="AP Vouchers Batch List">
                  <font>
                    <Font name="System Bold" size="14.0" />
                  </font>
                </Label>
                <Button fx:id="btnClose" cancelButton="true" layoutX="513.0" layoutY="27.0" mnemonicParsing="false" text="Close" />
                <Button id="btnClose" fx:id="apvRefresh" cancelButton="true" layoutX="185.0" layoutY="27.0" mnemonicParsing="false" onAction="#opentables" text="Refresh" />
              </children>
            </Pane>
            <TableView fx:id="tblMainList" layoutX="0.0" layoutY="53.0" prefHeight="323.0" prefWidth="580.0">
              <columns>
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="91.0" text="Date Entered" fx:id="colDateEntered" />
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="100.0" text="Created By" fx:id="colCreatedBy" />
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="261.0" text="Description" fx:id="colDescription" />
              </columns>
            </TableView>
          </children>
        </AnchorPane>
      </center>
      <padding>
        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
      </padding>
    </BorderPane>
  </children>
  <stylesheets>
    <URL value="@apvoucher_batchgrid.css" />
  </stylesheets>
</AnchorPane>

THANK YOU for the answer. Way to many years in case insensitive languages. This has been a quick and dirty exercise for me to learn java and the latest & greatest stuff or as I like to say New Exciting Technology (NExT!)

For anyone looking at the answer and still not completely clued in, here are the changes that made the code work properly.

colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("Denteredon"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("CDesc"));
colEnteredBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("Ccreatedby"));


    public class sresult {

        private String Denteredon;
        private String Ccreatedby;
        private String CDesc;

        public sresult(String T, String d, String c) {
            this.Ccreatedby = T;
            this.Denteredon = d;
            this.CDesc = c;
        }

        public String getCcreatedby() {
            return Ccreatedby;
        }

        public void setCreatedby(String T) {
            Ccreatedby = T;
        }

        public String getDenteredon() {
            return Denteredon;
        }

        public void setDenteredon(String d) {
            Denteredon = d;
        }

        public String getCDesc() {
            return CDesc;
        }

        public void setCDesc(String c) {
            CDesc = c;
        }
    }
}

Answer

jewelsea picture jewelsea · Sep 24, 2013

This question is really a duplicate of: Javafx PropertyValueFactory not populating Tableview, but I'll specifically address your specific case, so it's clear.

Background

PropertyValueFactory uses reflection to determine the methods to get and set data values as well as to retrieve bindable properties from your model class. The pattern followed is:

PropertyValueType getName()
void setName(PropertyValueType value)
PropertyType nameProperty()

Where "name" is the string specified in the PropertyValueFactory constructor. The first letter of the property name in the getter and setter is capitalized (by java bean naming convention).

Why your application doesn't work

You have these three expressions:

new PropertyValueFactory<sresult, String>("DateEntered")
new PropertyValueFactory<sresult, String>("cDesc")
new PropertyValueFactory<sresult, String>("CreatedBy")

For your sample properties, the PropertyValueFactory will look for these methods:

"DateEntered" => getDateEntered()
"cDesc" => getCDesc()
"CreatedBy" => getCreatedBy()

And you have these three getters on your sresult class:

getDateEntered()
getcDesc()
getEnteredBy()

Only getDateEntered() is going to be picked up by the PropertyValueFactory because that is the only matching method defined in the sresult class.

Advice

You will have to adopt Java standards if you want the reflection in PropertyValueFactory to work (the alternative is to not use the PropertyValueFactory and instead write your own cell factories from scratch).

Adopting Java camel case naming conventions also makes it easier for Java developers to read your code.