JavaFX:使用map填充tableview

时间:2017-11-18 07:25:49

标签: javafx tableview fxml

我开始学习JavaFX,我想用我的数据库中的数据填充我的tableview。我已经了解到我可以使用地图来构建数据,但它并没有起作用。 tableview只显示列'名称但没有行。

这是我的代码:

Main.java

for (let i = 0; i < 100; i++) {
    setTimeout(() => console.log("test"), 1000 * i);
}

MainWindowControl.java

package application;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.fxml.FXMLLoader;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            AnchorPane root = (AnchorPane)FXMLLoader.load(getClass().getResource("MainWindow.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

MainWindow.fxml

package application;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;

public class MainWindowController {

    @FXML
    private TableView<Map<Integer, String>> tableView = new TableView<>(generateDataInMap());

    final static Integer first = 1;

    public void openDatabase() throws SQLException {
        Connection connection = DriverManager.getConnection("jdbc:sqlite:test.db");
        Statement statement = connection.createStatement();
        ResultSet rSet = statement.executeQuery("select * from myTable");

        int col = rSet.getMetaData().getColumnCount();

        for (int i = 1; i <= col; i++) {
            rSet = statement.executeQuery("select * from myTable");
            Integer key = 1;
            String name = rSet.getMetaData().getColumnName(i);
            TableColumn<Map<Integer, String>, String> tableColumn = new TableColumn<>(name);
            tableColumn.setCellValueFactory(new MapValueFactory(key));
            tableView.getColumns().add(tableColumn);
        }
    }

    private ObservableList<Map<Integer, String>> generateDataInMap(){
        Connection connection = null;
        ObservableList<Map<Integer, String>> alldata = FXCollections.observableArrayList();
        try {
            connection = DriverManager.getConnection("jdbc:sqlite:test.db");
            Statement statement = connection.createStatement();
            ResultSet rSet = statement.executeQuery("select * from myTable");

            int col = rSet.getMetaData().getColumnCount();
            while(rSet.next()) {
                Map<Integer, String> dataRow = new HashMap<>();
                for (int i = 1; i <= col; i++) {
                    String value = rSet.getString(i);
                    dataRow.put(i, value);
                }
                alldata.add(dataRow);
            }

            connection.close();
            return alldata;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

您知道我的代码中的错误在哪里吗?我试图模拟SQLiteStudio的功能,当我选择数据库时,数据将填充tableview。

1 个答案:

答案 0 :(得分:0)

您正在控制器类的初始值设定项中创建TableView。此TableView填充了数据,但实例永远不会显示在场景中,因为FXMLLoader会从fxml创建一个实例。

initialize()方法中进行这样的初始化。注入所有对象后,此方法由FXMLLoader运行,使屏幕上显示的tableView实例可访问。

附加说明:

  • 您将始终为key的{​​{1}}传递给值工厂。相反,您应该使用1
  • 您为每个列重新查询数据库,始终获取表中的每一行。这是非常低效的。只需执行一次查询。考虑将结果用于初始化行和列。
  • 考虑分离数据访问和查看。您可以通过将数据传递给控制器​​来执行此操作,请参阅Passing Parameters JavaFX FXML
i

请注意,上面修改过的代码版本要求您删除@FXML private TableView<Map<Integer, String>> tableView; @FXML private void initialize() throws Exception { try (Connection connection = DriverManager.getConnection("jdbc:sqlite:test.db"); Statement statement = connection.createStatement()) { ResultSet rSet = statement.executeQuery("select * from myTable"); openDatabase(rSet); tableView.setItems(generateDataInMap(rSet)); } // TODO: Exception handling??? } private void openDatabase(ResultSet rSet) throws SQLException { final ResultSetMetaData metadata = rSet.getMetaData(); final int col = metadata.getColumnCount(); for (int i = 1; i <= col; i++) { String name = metadata.getColumnName(i); TableColumn<Map<Integer, String>, String> tableColumn = new TableColumn<>(name); tableColumn.setCellValueFactory(new MapValueFactory(i)); tableView.getColumns().add(tableColumn); } } private ObservableList<Map<Integer, String>> generateDataInMap(ResultSet rSet) { ObservableList<Map<Integer, String>> alldata = FXCollections.observableArrayList(); final int col = rSet.getMetaData().getColumnCount(); while(rSet.next()) { Map<Integer, String> dataRow = new HashMap<>(); for (int i = 1; i <= col; i++) { String value = rSet.getString(i); dataRow.put(i, value); } alldata.add(dataRow); } return alldata; } 事件处理程序,但由于添加行但未初始化列没有意义,因此我将调用移至onAction方法并修改了签名的方式不允许您再将其用作initialize