-1

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

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?

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.

  • 1
    From the SQL statement, it looks like you know how many columns you're going to have, and what the data in those columns represent. Is that correct? If so, can you explicitly include that information in the question? (BTW, I don't think offering to pay for answers is considered acceptable on this forum. It is certainly not in the spirit of the site.) – James_D May 11 '17 at 23:58
  • @James_D added: 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 – Lennert Bontinck May 12 '17 at 00:04
  • have you reffered this [post](http://stackoverflow.com/questions/17316328/default-table-model-in-javafx) suppose you can find a better solution from this post. – Rajith Pemabandu May 12 '17 at 00:05
  • Also see http://stackoverflow.com/questions/25651641/javafx-mysql-connection-example-please – James_D May 12 '17 at 00:27

1 Answers1

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.

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.

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);
        }
    }
});
James_D
  • 201,275
  • 16
  • 291
  • 322
  • You are the hero every student needs but none deserve, had to edit quite a bit to make it work like I wanted but it finally works like a charm in a javafx stackpane! rock on dude! – Lennert Bontinck May 12 '17 at 11:17