Populating TableView in JavaFX

2019-06-14 09:48发布

问题:

I am a newbie in here, my Table View in JavFX namely as tblStudent is NOT containing the
records that I want. How to do this, please help me.

    public void populateData(){
      Connection c ;
      data = FXCollections.observableArrayList();
      try{
        c = ConnectionClass.connect();
        //SQL FOR SELECTING ALL OF CUSTOMER
        String SQL = "SELECT * FROM `student`";
        //ResultSet
        ResultSet rs = c.createStatement().executeQuery(SQL);


        studentIDCol = new TableColumn("Student ID");
        nameCol = new TableColumn("Name");
        addressCol = new TableColumn("Address");
        ageCol = new TableColumn("Age");
        contactnoCol = new TableColumn("Contact Number");

        while(rs.next()){
            //Iterate Row
            ObservableList<String> row = FXCollections.observableArrayList();

            row.add(rs.getString("id"));
            row.add(rs.getString("name"));
            row.add(rs.getString("address"));
            row.add(rs.getString("age"));
            row.add(rs.getString("contact_num"));

            System.out.println("Row [1] added "+row );
            data.add(row);

        }

        //FINALLY ADDED TO TableView
        tblStudent.getItems().setAll(data);
      }catch(Exception e){
          e.printStackTrace();
          System.out.println("Error on Building Data");             
      }
 }

Anyone who knows this?

回答1:

You need to set the cell value factory to all your columns like this:

TableColumn<ObservableList<String>, String> studentIDCol  = new TableColumn<>("Student ID");
    studentIDCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {         
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(0));
        }
    });

And also I recommend you to extract your query to a service, because the query will block the JavaFX Thread. Check out http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

Check this full example with test data.

public void start(Stage stage) throws Exception {
    VBox vbox = new VBox(10.0);
    vbox.setAlignment(Pos.CENTER);

    final TableView<ObservableList<String>> table = new TableView<>();

    TableColumn<ObservableList<String>, String> studentIDCol  = new TableColumn<>("Student ID");
    studentIDCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {         
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(0));
        }
    }); 

    TableColumn<ObservableList<String>, String> nameCol = new TableColumn<>("Name");
    nameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {          
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(1));
        }
    });     

    TableColumn<ObservableList<String>, String> addressCol  = new TableColumn<>("Address");
    addressCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {           
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(2));
        }
    });     

    TableColumn<ObservableList<String>, String> ageCol  = new TableColumn<>("Age");
    ageCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {           
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(3));
        }
    });     

    TableColumn<ObservableList<String>, String> contactnoCol  = new TableColumn<>("Contact Number");
    contactnoCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {         
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(4));
        }
    });     

    table.getColumns().add(studentIDCol);
    table.getColumns().add(nameCol);
    table.getColumns().add(addressCol);
    table.getColumns().add(ageCol);
    table.getColumns().add(contactnoCol);   

    final ProgressBar bar = new ProgressBar(-1);
    bar.setVisible(false);

    final Button button = new Button("Fill");
    button.setOnAction(new EventHandler<ActionEvent>() {            
        @Override
        public void handle(ActionEvent event) {
            final Service<ObservableList<ObservableList<String>>> service = new Service<ObservableList<ObservableList<String>>>() {                 
                @Override
                protected Task<ObservableList<ObservableList<String>>> createTask() {
                    return new Task<ObservableList<ObservableList<String>>>() {
                        @Override
                        protected ObservableList<ObservableList<String>> call() throws Exception {
                            ObservableList<ObservableList<String>> items = FXCollections.observableArrayList();
                            items.add(FXCollections.observableArrayList("1", "2", "3", "4", "5"));
                            items.add(FXCollections.observableArrayList("1", "2", "3", "4", "5"));
                            items.add(FXCollections.observableArrayList("1", "2", "3", "4", "5"));
                            //Here the code for the query
                            Thread.sleep(5000);//To see the progress
                            return items;
                        }
                    };
                }
            };

            bar.visibleProperty().bind(service.runningProperty());
            button.disableProperty().bind(service.runningProperty());
            table.itemsProperty().bind(service.valueProperty());

            service.start();
        }
    });     

    vbox.getChildren().addAll(table, button, bar);
    Scene scene = new Scene(vbox, 300, 300);
    stage.setScene(scene);
    stage.show();
}

If you are using a FXML file. You need to skip the initialization step of the TableColumn.

Declare the TableColumn as a fields in the file in your controller class with the @FXML annotation. Ensure you implements javafx.fxml.Initializable. And in the initialize method you can do the configuration side for every column. And avoid the add of the columns to the table, because they already are in the table view.

Here is a sample if your are defining your TableView in your FXML like this:

<TableView layoutX="145.0" layoutY="76.0" prefHeight="200.0" prefWidth="200.0">
  <columns>
    <TableColumn prefWidth="75.0" text="Student ID" fx:id="studentIDCol" />
    <TableColumn prefWidth="75.0" text="Name" fx:id="nameCol" />
    <TableColumn prefWidth="75.0" text="Address" fx:id="addressCol" />
    <TableColumn prefWidth="75.0" text="Age" fx:id="ageCol" />
  </columns>
</TableView>

Then your controller class will be like this:

class YourTest implements javafx.fxml.Initializable{
//More Code
@FXML
TableColumn<ObservableList<String>, String> studentIDCol;
@FXML
TableColumn<ObservableList<String>, String> nameCol;
@FXML
TableColumn<ObservableList<String>, String> addressCol;
@FXML
TableColumn<ObservableList<String>, String> ageCol;
//More of your code 
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    studentIDCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {         
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(0));
        }
    }); 

    nameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {          
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(1));
        }
    });             

    addressCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {           
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(2));
        }
    });     

    ageCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {           
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(3));
        }
    });     

    contactnoCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<String>,String>, ObservableValue<String>>() {         
        @Override
        public ObservableValue<String> call(CellDataFeatures<ObservableList<String>, String> cdf) {     
            return new SimpleStringProperty(cdf.getValue().get(4));
        }
    });  
}
//More of your Code
}

Hope it helps.