需要帮助将DefaultTableModel转换为Table View JavaFX

时间:2022-06-30 21:32:08

After hours and hours of trying i'm getting close to my deadline for a project and still haven't gotten any solution for my rather easy problem. I need to fill a tableview with data from SQL Query but I can't get it to work even if i copy paste online examples... I need the same result as the following code

经过几个小时的尝试,我已接近我的项目截止日期,仍然没有得到任何解决我相当容易的问题。我需要使用SQL Query中的数据填充tableview,但即使我复制粘贴在线示例,我也无法使其工作...我需要与以下代码相同的结果

public DefaultTableModel buildTableModel() {
        ResultSetMetaData metaData;
        try (Connection conn = DriverManager.getConnection(MapperConfig.JDBC_URL)) {
            PreparedStatement queryOpgeslagenGames = conn.prepareStatement("");
            ResultSet rs = queryOpgeslagenGames.executeQuery("SELECT spellen.spelID, spellen.spelNaam AS 'Naam van Spel', group_concat( naam separator ', ') AS 'Deelnemende spelers' FROM spellen RIGHT JOIN spelers ON spellen.spelID =     spelers.spelID GROUP BY spellen.spelID");
            metaData = rs.getMetaData();
            // names of columns
            Vector<String> columnNames = new Vector<String>();
            int columnCount = metaData.getColumnCount();
            for (int column = 1; column <= columnCount; column++) {
                columnNames.add(metaData.getColumnName(column));
            }

            // data of the table
            Vector<Vector<Object>> data = new Vector<Vector<Object>>();
            while (rs.next()) {
                Vector<Object> vector = new Vector<Object>();
                for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
                    vector.add(rs.getObject(columnIndex));
                }
                data.add(vector);
            }
        return new DefaultTableModel(data, columnNames);
        } catch (SQLException ex) {
            for (Throwable t : ex) {
                t.printStackTrace();
            }
        }
        return new DefaultTableModel();
    }

but since i need to use it in JavaFX i can't use Jtable and need to use table view. Can someone convert the code for me? or tell me how to use DefaultTableModel to make a table view?

但由于我需要在JavaFX中使用它,我不能使用Jtable并需要使用表视图。有人可以为我转换代码吗?或告诉我如何使用DefaultTableModel来制作表格视图?

The table wil always have 3 colums, first being the gameID, second the game save file name and third a collection of names from the people in the game.

该表总是有3个列,首先是gameID,第二个是游戏保存文件名,第三个是游戏中人员的名字集合。

1 个解决方案

#1


1  

JavaFX TableViews are based on a model in which each row is represented by an object. Each column has an associated function (the cellValueFactory) that maps the object for a row to the value to be displayed in the corresponding cell in that column.

JavaFX TableViews基于一个模型,其中每一行由一个对象表示。每列都有一个关联函数(cellValueFactory),它将行的对象映射到要在该列的相应单元格中显示的值。

So you should start by defining a class that represents the item in each row. It's best to do this using the JavaFX properties pattern, which will allow the table to bind easily to the data in the instances of this class.

因此,您应该首先定义一个表示每行中项目的类。最好使用JavaFX属性模式执行此操作,这将允许表轻松绑定到此类实例中的数据。

public class Game {

    // maybe an IntegerProperty?
    private final StringProperty id = new SimpleStringProperty();
    private final StringProperty saveFileName = new SimpleStringProperty();
    private final ListProperty<String> playerNames = new SimpleListProperty<>(FXCollections.observableArrayList()); 

    public Game(String id, String saveFileName, String... playerNames) {
        setId(id);
        setSaveFileName(saveFileName);
        playerNames.get().setAll(playerNames);
    }

    public StringProperty idProperty() {
        return id ;
    }

    public final String getId() {
        return idProperty().get();
    }

    public final void setId(String id) {
        idProperty().set(id);
    }

    // similarly for saveFileName...

    public ListProperty<String> playerNamesProperty() {
        return playerNames ;
    }

    public final ObservableList<String> getPlayerNames() {
        return playerNamesProperty().get();
    }

    public final void setPlayerNames(ObservableList<String> playerNames) {
        playerNamesProperty().set(playerNames);
    }
}

Now your data accessor method should look like:

现在您的数据访问器方法应如下所示:

public ObservableList<Game> buildTableModel() {

    try (Connection conn = DriverManager.getConnection(MapperConfig.JDBC_URL)) {
        PreparedStatement queryOpgeslagenGames = conn.prepareStatement("");
        ResultSet rs = queryOpgeslagenGames.executeQuery("SELECT spellen.spelID, spellen.spelNaam AS 'Naam van Spel', group_concat( naam separator ', ') AS 'Deelnemende spelers' FROM spellen RIGHT JOIN spelers ON spellen.spelID =     spelers.spelID GROUP BY spellen.spelID");
        // data of the table
        ObservableList<Game> games = FXCollections.observableArrayList();
        while (rs.next()) {
            String id = rs.get(1);
            String saveFileName = rs.get(2);
            String[] playerNames = rs.get(3).split(", ");
            Game game = new Game(id, saveFileName, playerNames);
            games.add(game);
        }
        return games ;
    } catch (SQLException ex) {
        for (Throwable t : ex) {
            t.printStackTrace();
        }
    }
    return FXCollections.observableArrayList();
}

And finally you set the table up with

最后你设置了表格

TableView<Game> table = new TableView<>();
TableColumn<Game, String> idColumn = new TableColumn<>("ID");
idColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty());
TableColumn<Game, String> saveFileNameColumn = new TableColumn<>("Save file name");
saveFileNameColumn.setCellValueFactory(cellData -> cellData.getValue().saveFileNameProperty());
TableColumn<Game, ObservableList<String>> playerNamesColumn = new TableColumn<>("Player names");
playerNamesColumn.setCellValueFactory(cellData -> callData.getValue().playerNamesProperty());

table.setItems(buildTableModel());

table.getColumns().addAll(idColumn, saveFileNameColumn, playerNamesColumn);

You can additionally improve the rendering in the player names column with something like

您还可以使用类似的内容改进播放器名称列中的渲染

playerNamesColumn.setCellFactory(col -> new TableCell<Game, ObservableList<String>>() {
    @Override
    protected void updateItem(ObservableList<String> playerNames, boolean empty) {
        super.updateItem(playerNames, empty);
        if (empty) {
            setText(null);
        } else {
            setText(String.join(", ", playerNames));
        }
    }
});

or, for a more sophisticated display:

或者,对于更复杂的显示:

playerNamesColumn.setCellFactory(col -> new TableCell<Game, ObservableList<String>>() {

    private final ListView<String> listView = new ListView<>();

    @Override
    protected void updateItem(ObservableList<String> playerNames, boolean empty) {
        super.updateItem(playerNames, empty);
        if (empty) {
            setGraphic(null);
        } else {
            listView.setItems(playerNames);
            setGraphic(listView);
        }
    }
});

#1


1  

JavaFX TableViews are based on a model in which each row is represented by an object. Each column has an associated function (the cellValueFactory) that maps the object for a row to the value to be displayed in the corresponding cell in that column.

JavaFX TableViews基于一个模型,其中每一行由一个对象表示。每列都有一个关联函数(cellValueFactory),它将行的对象映射到要在该列的相应单元格中显示的值。

So you should start by defining a class that represents the item in each row. It's best to do this using the JavaFX properties pattern, which will allow the table to bind easily to the data in the instances of this class.

因此,您应该首先定义一个表示每行中项目的类。最好使用JavaFX属性模式执行此操作,这将允许表轻松绑定到此类实例中的数据。

public class Game {

    // maybe an IntegerProperty?
    private final StringProperty id = new SimpleStringProperty();
    private final StringProperty saveFileName = new SimpleStringProperty();
    private final ListProperty<String> playerNames = new SimpleListProperty<>(FXCollections.observableArrayList()); 

    public Game(String id, String saveFileName, String... playerNames) {
        setId(id);
        setSaveFileName(saveFileName);
        playerNames.get().setAll(playerNames);
    }

    public StringProperty idProperty() {
        return id ;
    }

    public final String getId() {
        return idProperty().get();
    }

    public final void setId(String id) {
        idProperty().set(id);
    }

    // similarly for saveFileName...

    public ListProperty<String> playerNamesProperty() {
        return playerNames ;
    }

    public final ObservableList<String> getPlayerNames() {
        return playerNamesProperty().get();
    }

    public final void setPlayerNames(ObservableList<String> playerNames) {
        playerNamesProperty().set(playerNames);
    }
}

Now your data accessor method should look like:

现在您的数据访问器方法应如下所示:

public ObservableList<Game> buildTableModel() {

    try (Connection conn = DriverManager.getConnection(MapperConfig.JDBC_URL)) {
        PreparedStatement queryOpgeslagenGames = conn.prepareStatement("");
        ResultSet rs = queryOpgeslagenGames.executeQuery("SELECT spellen.spelID, spellen.spelNaam AS 'Naam van Spel', group_concat( naam separator ', ') AS 'Deelnemende spelers' FROM spellen RIGHT JOIN spelers ON spellen.spelID =     spelers.spelID GROUP BY spellen.spelID");
        // data of the table
        ObservableList<Game> games = FXCollections.observableArrayList();
        while (rs.next()) {
            String id = rs.get(1);
            String saveFileName = rs.get(2);
            String[] playerNames = rs.get(3).split(", ");
            Game game = new Game(id, saveFileName, playerNames);
            games.add(game);
        }
        return games ;
    } catch (SQLException ex) {
        for (Throwable t : ex) {
            t.printStackTrace();
        }
    }
    return FXCollections.observableArrayList();
}

And finally you set the table up with

最后你设置了表格

TableView<Game> table = new TableView<>();
TableColumn<Game, String> idColumn = new TableColumn<>("ID");
idColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty());
TableColumn<Game, String> saveFileNameColumn = new TableColumn<>("Save file name");
saveFileNameColumn.setCellValueFactory(cellData -> cellData.getValue().saveFileNameProperty());
TableColumn<Game, ObservableList<String>> playerNamesColumn = new TableColumn<>("Player names");
playerNamesColumn.setCellValueFactory(cellData -> callData.getValue().playerNamesProperty());

table.setItems(buildTableModel());

table.getColumns().addAll(idColumn, saveFileNameColumn, playerNamesColumn);

You can additionally improve the rendering in the player names column with something like

您还可以使用类似的内容改进播放器名称列中的渲染

playerNamesColumn.setCellFactory(col -> new TableCell<Game, ObservableList<String>>() {
    @Override
    protected void updateItem(ObservableList<String> playerNames, boolean empty) {
        super.updateItem(playerNames, empty);
        if (empty) {
            setText(null);
        } else {
            setText(String.join(", ", playerNames));
        }
    }
});

or, for a more sophisticated display:

或者,对于更复杂的显示:

playerNamesColumn.setCellFactory(col -> new TableCell<Game, ObservableList<String>>() {

    private final ListView<String> listView = new ListView<>();

    @Override
    protected void updateItem(ObservableList<String> playerNames, boolean empty) {
        super.updateItem(playerNames, empty);
        if (empty) {
            setGraphic(null);
        } else {
            listView.setItems(playerNames);
            setGraphic(listView);
        }
    }
});