【问题标题】:Populating TableView with data from database.Failed to set rows使用数据库中的数据填充 TableView。无法设置行
【发布时间】:2014-08-17 15:23:27
【问题描述】:

当我从数据库中检索数据时,我碰壁了。我设法将列名输入到我的表中,这没问题,并且可以正常工作。

当我尝试添加行时,我发现没有数据添加到我的表格视图中,我试图从代表单行的字符串数组中添加行。我不知道用户会要求多少列等查询以及表有多大,所以我无法创建行对象和代表每一列的所有属性。

问题是如何用我从数据库中成功检索到的行填充我的表格视图,格式为每行的 String[]。

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

检索行..(Works debug 打印所有数据正确)

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);
            }
    });

加入表格

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

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

        }

回答后编辑工作代码

为遇到与我相同问题的人提供的工作代码。唯一需要的工厂真的是 ValueFactory。这是我的两种方法

  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;
            }
        }

【问题讨论】:

  • 您在哪里创建 setCellFactory注意: 我认为最好的方法是首先将你的 sql 行解析为一个对象,然后填充 tableview。
  • @Kyllopardiun 问题是当我不知道表有多大/用户将选择哪些列时,我无法使用对象。而且我肯定无法为所有情况创建对象。我想我知道创建对象/属性并将它们放入可观察列表很容易。然后它应该可以工作,但我不能那样做。我到底需要 cellFactory 做什么?
  • 这是一个在不知道有多少列时添加列的示例。 stackoverflow.com/a/20774549/2855515 您可能可以从结果集元数据中获取标题。另一个包含大量无关代码的示例。 stackoverflow.com/a/24112797/2855515

标签: java database javafx tableview


【解决方案1】:

如果你想让它工作,你需要设置一些工厂。

在下面的示例中,我没有从 SQL 服务器获取元素,但我相信足以让您了解如何完成此操作。

请注意,它只填充顺序值,但它仍然具有与方法 createTable() 中的 header 一样多的列。

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);
        }
    }
}

【讨论】:

  • 感谢这个例子,它为我指明了正确的方向。我的代码现在与你的不同,唯一真正需要的工厂是值工厂。我猜是因为 SimpleIntegerProperty(在我的例子中是字符串)在回调中返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 2018-11-22
  • 2020-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多