Populating TableView with data from database.Faile

2020-03-08 00:47发布

问题:

I hit a wall when i retrieve data from database.I managed to get column names into my table which is ok and works as it shoud.

Bud when i try to add rows i find that no data has been added into my tableview,im trying to add rows from array of string which represent single row.I have no idea how many columns etc will user ask for with his query and how big table is so i cant create row object and all the properties which represent each column.

Question is how do i populate my tableview with rows that i have retrieved successfully from database in format of String[] each row.

 private ObservableList<String[]> dataRows=FXCollections.observableArrayList();

Retrieve rows..(Works debug prints all data correct)

while (this.resultSet.next()) {

        for (int i = 1; i < this.resultSetMd.getColumnCount() + 1; i++) {
            rows.add(resultSet.getString(i));

        }
        dataRows.add(rows.toArray(new String[rows.size()]));
        rows.removeAll(rows);

        //TODO DELETE row debugger debug
        dataRows.forEach((r)->{
            System.out.println("Row---------");
            for(String s:r){
                System.out.println("Debug row value- "+s);
            }
    });

Adding into table

  private void populateTable() {
            dpcontroller.tableView.getColumns().addAll(columns); //columns work

            dpcontroller.tableView.setItems(dataRows); //no data entered

        }

EDIT- WORKING CODE AFTER ANSWER

Working code for people who will encounter same problem as i did.Only needed factory was really ValueFactory.Here are my two methods

  private void populateTable() {
            for (int rowNumber = 0; rowNumber < dataRows.size(); rowNumber++) {
                for (TableColumn tc : columns) {

                    tc.setCellValueFactory(new ValueFactory(columns.indexOf(tc),rowNumber));
                    dpcontroller.tableView.getColumns().add(tc);
                }
            }
            dpcontroller.tableView.setItems(dataRows);

        }
        private class ValueFactory implements Callback {

            private int rowNumber;
            private int columnNumber;

            public ValueFactory(int columnNumber, int rowNumber) {
                this.columnNumber = columnNumber;
                this.rowNumber = rowNumber;
            }

            @Override
            public Object call(Object o) {
                SimpleStringProperty stringProperty = new SimpleStringProperty(dataRows.get(rowNumber)[columnNumber]);
                return stringProperty;
            }
        }

回答1:

You will need to set some Factories, if you want to get this working.

In the example below, I do not get elements from a SQL server, but I believe will be enough for you to see how to accomplish this.

Note that it just fill with sequential values, but still it will have as many columns as the header in the method createTable().

package table;

import com.sun.javafx.collections.ObservableListWrapper;
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.util.Collections;
import java.util.List;

public class TableDemo extends Application {
    private int rowIndex = 0;
    private int elementIndex = 0;
    final TableView tableView = new TableView();
    ObservableList<String[]> dataRows = FXCollections.observableArrayList();
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        FlowPane pane = new FlowPane();
        tableView.setRowFactory(new CountingRowFactory());
        createTable();
        pane.getChildren().add(tableView);
        List items = Collections.singletonList(new Object());
        tableView.setItems(dataRows);
        stage.setScene(new Scene(pane));
        stage.show();
    }

    private TableColumn createColumn(String header) {
        TableColumn column = new TableColumn(header);
        column.setCellFactory(new CellFactory());
        column.setCellValueFactory(new CountingValueFactory());
        return column;
    }

    private static class CellFactory implements Callback {
        @Override
        public Object call(Object column) {
            return new TableCell() {
                @Override
                protected void updateItem(Object o, boolean b) {
                    super.updateItem(o, b);
                    setText(String.valueOf(o));
                }
            };
        }
    }

    private class CountingRowFactory implements Callback {
        @Override
        public Object call(Object o) {
            TableRow row = new TableRow();
            row.setUserData(rowIndex);
            rowIndex++;
            return row;
        }
    }

    private class CountingValueFactory implements Callback {
        @Override
        public Object call(Object o) {
            SimpleIntegerProperty property = new SimpleIntegerProperty(elementIndex);
            elementIndex++;
            return property;
        }
    }
    public void createTable(){
        String[] header  = {"a","b","c","d","e","f","g","h"};
        for(String s: header)
            tableView.getColumns().add(createColumn(s));
        for(int i=0;i<30;i++){
            String[] temp  = header;
            for(int j=0;j<temp.length;j++)
                temp[j] += + i ; 
            dataRows.add(temp);
        }
    }
}