JavaFX TableView Контекстное меню получить выбранный идентификатор - PullRequest
0 голосов
/ 21 февраля 2020

У меня есть TableView, где я отображаю данные из моей базы данных. Сам TableView не жестко запрограммирован для конкретной таблицы c, но вместо этого он добавляет столбцы и данные. Я добавил контекстное меню, поэтому, когда пользователь щелкает правой кнопкой мыши по элементу, он удаляется. Это работает нормально, но я не знаю, как получить идентификатор, который является первым столбцом. Обратите внимание, что я не хочу, чтобы выбранный индекс, но идентификатор из tableView (первый столбец).

Опрошенный фрагмент:

removeMenuItem.setOnAction(event -> {
    System.out.println(row.getItem()); // HERE

    this.tableView.getItems().remove(row.getItem());
});

В основном, row.getItem() возвращает запись:

[2, Name, Stuff, Test Test, Category]

Вопрос в том, как мне получить идентификатор (в данном случае 2) или имя?

Полный код:

package controllers;

import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.util.Callback;

import java.sql.ResultSet;
import java.sql.SQLException;

public class TableController {

    @FXML
    private Label descriptionLabel;

    @FXML
    private TableView tableView;

    public void setTableResultSet(String label, ResultSet resultSet) throws SQLException {
        // Create context menu
        createContextMenu();

        // Set label text
        descriptionLabel.setText(label);

        // Resolve columns
        ObservableList<ObservableList> data = resolveTableColumns(resultSet);

        // Add records
        addTableRecords(resultSet, data);
    }

    /**
     * Create a context menu responsible for removing items.
     */
    private void createContextMenu() {
        tableView.setRowFactory(tableView -> {
            final TableRow row = new TableRow();
            final ContextMenu contextMenu = new ContextMenu();
            final MenuItem removeMenuItem = new MenuItem("Remove");
            removeMenuItem.setOnAction(event -> {
                System.out.println(row.getItem()); // HERE

                this.tableView.getItems().remove(row.getItem());
            });
            contextMenu.getItems().add(removeMenuItem);

            // Set context menu on row, but use a binding to make it only show for non-empty rows:
            row.contextMenuProperty().bind(
                    Bindings.when(row.emptyProperty())
                            .then((ContextMenu) null)
                            .otherwise(contextMenu)
            );

            return row;
        });
    }

    /**
     * Resolves table columns based on a ResultSet.
     *
     * @param resultSet the ResultSet.
     * @return
     * @throws SQLException
     */
    private ObservableList<ObservableList> resolveTableColumns(ResultSet resultSet) throws SQLException {
        ObservableList<ObservableList> data = FXCollections.observableArrayList();
        for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
            final int j = i;
            TableColumn col = new TableColumn(resultSet.getMetaData().getColumnName(i + 1));
            col.setCellValueFactory((Callback<TableColumn.CellDataFeatures<ObservableList, String>, ObservableValue<String>>) param -> {
                return new SimpleStringProperty(param.getValue().get(j).toString());
            });
            tableView.getColumns().add(col);
        }
        return data;
    }

    /**
     * Adds table data from a ResultSet.
     *
     * @param resultSet the ResultSet.
     * @param data      the data.
     * @throws SQLException
     */
    private void addTableRecords(ResultSet resultSet, ObservableList<ObservableList> data) throws SQLException {
        while (resultSet.next()) {
            ObservableList<String> row = FXCollections.observableArrayList();
            for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) {
                row.add(resultSet.getString(i));
            }
            data.add(row);
        }
        tableView.setItems(data);
    }
}

Редактирование на основе комментария @ James_D:

package controllers;

import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.util.Callback;

import java.sql.ResultSet;
import java.sql.SQLException;

public class TableController {

    @FXML
    private Label descriptionLabel;

    @FXML
    private TableView<ObservableList<String>> tableView;

    public void setTableResultSet(String label, ResultSet resultSet) throws SQLException {
        // Create context menu
        createContextMenu();

        // Set label text
        descriptionLabel.setText(label);

        // Resolve columns
        ObservableList<ObservableList<String>> data = resolveTableColumns(resultSet);

        // Add records
        addTableRecords(resultSet, data);
    }

    /**
     * Create a context menu responsible for removing items.
     */
    private void createContextMenu() {
        tableView.setRowFactory(tableView -> {
            final TableRow<ObservableList<String>> row = new TableRow<>();
            final ContextMenu contextMenu = new ContextMenu();
            final MenuItem removeMenuItem = new MenuItem("Изтрий");
            removeMenuItem.setOnAction(event -> {
                System.out.println(row.getItem().get(1));

                this.tableView.getItems().remove(row.getItem());
            });
            contextMenu.getItems().add(removeMenuItem);

            // Set context menu on row, but use a binding to make it only show for non-empty rows:
            row.contextMenuProperty().bind(
                    Bindings.when(row.emptyProperty())
                            .then((ContextMenu) null)
                            .otherwise(contextMenu)
            );

            return row;
        });
    }

    /**
     * Resolves table columns based on a ResultSet.
     *
     * @param resultSet the ResultSet.
     * @return
     * @throws SQLException
     */
    private ObservableList<ObservableList<String>> resolveTableColumns(ResultSet resultSet) throws SQLException {
        ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
        for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
            final int j = i;
            TableColumn col = new TableColumn(resultSet.getMetaData().getColumnName(i + 1));
            col.setCellValueFactory((Callback<TableColumn.CellDataFeatures<ObservableList, String>, ObservableValue<String>>) param -> {
                return new SimpleStringProperty(param.getValue().get(j).toString());
            });
            tableView.getColumns().add(col);
        }
        return data;
    }

    /**
     * Adds table data from a ResultSet.
     *
     * @param resultSet the ResultSet.
     * @param data      the data.
     * @throws SQLException
     */
    private void addTableRecords(ResultSet resultSet, ObservableList<ObservableList<String>> data) throws SQLException {
        while (resultSet.next()) {
            ObservableList<String> row = FXCollections.observableArrayList();
            for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) {
                row.add(resultSet.getString(i));
            }
            data.add(row);
        }
        tableView.setItems(data);
    }
}

1 Ответ

2 голосов
/ 21 февраля 2020

Не используйте необработанные типы: таким образом, вы можете получить доступ к соответствующим методам для данных, которые вы извлекаете из таблицы (не нужно никуда спускаться).

В частности, вы заявляете, что представляете свои данные как ObservableList<ObservableList>, что означает, что каждая строка представлена ​​как (необработанная) ObservableList. Поскольку, глядя на ваш метод addTableRecords, каждый элемент строки представляет собой String, строки должны быть представлены как ObservableList<String>, а общие данные как ObservableList<ObservableList<String>>.

TableView и связанные элементы пользовательского интерфейса также должны быть параметризованы: т.е. вы должны использовать

  • TableView<ObservableList<String>>
  • TableColumn<ObservableList<String>, String>
  • TableRow<ObservableList<String>

Если вы сделаете эти изменения, то в вашем методе createContextMenu() у вас будет

TableRow<ObservableList<String>> row = new TableRow<>(); 

Следовательно, тип возвращаемого значения row.getItem() будет ObservableList<String>, и вы сможете вызывать методы, определенные в ObservableList (или, в более общем случае, List) возвращаемого значения. В частности, вызов get(...) вернет String в данную ячейку в строке:

String id = row.getItem().get(0);
String name = row.getItem().get(1);

et c.

Соберите все вместе, это выглядит как

package controllers;

import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.util.Callback;

import java.sql.ResultSet;
import java.sql.SQLException;

public class TableController {

    @FXML
    private Label descriptionLabel;

    @FXML
    private TableView<ObservableList<String>> tableView;

    public void setTableResultSet(String label, ResultSet resultSet) throws SQLException {
        // Create context menu
        createContextMenu();

        // Set label text
        descriptionLabel.setText(label);

        // Resolve columns
        ObservableList<ObservableList<String>> data = resolveTableColumns(resultSet);

        // Add records
        addTableRecords(resultSet, data);
    }

    /**
     * Create a context menu responsible for removing items.
     */
    private void createContextMenu() {
        tableView.setRowFactory(tableView -> {
            final TableRow<ObservableList<String>> row = new TableRow<>();
            final ContextMenu contextMenu = new ContextMenu();
            final MenuItem removeMenuItem = new MenuItem("Изтрий");
            removeMenuItem.setOnAction(event -> {
                String id = row.getItem().get(0);
                String name = row.getItem().get(1);
                // do whatever you need with id and name, etc.

                this.tableView.getItems().remove(row.getItem());
            });
            contextMenu.getItems().add(removeMenuItem);

            // Set context menu on row, but use a binding to make it only show for non-empty rows:
            row.contextMenuProperty().bind(
                    Bindings.when(row.emptyProperty())
                            .then((ContextMenu) null)
                            .otherwise(contextMenu)
            );

            return row;
        });
    }

    /**
     * Resolves table columns based on a ResultSet.
     *
     * @param resultSet the ResultSet.
     * @return
     * @throws SQLException
     */
    private ObservableList<ObservableList<String>> resolveTableColumns(ResultSet resultSet) throws SQLException {
        ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
        for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
            final int j = i;
            TableColumn<ObservableList<String>, String> col = new TableColumn<>(resultSet.getMetaData().getColumnName(i + 1));
            col.setCellValueFactory(param -> 
                new SimpleStringProperty(param.getValue().get(j))
            );
            tableView.getColumns().add(col);
        }
        return data;
    }

    /**
     * Adds table data from a ResultSet.
     *
     * @param resultSet the ResultSet.
     * @param data      the data.
     * @throws SQLException
     */
    private void addTableRecords(ResultSet resultSet, ObservableList<ObservableList<String>> data) throws SQLException {
        while (resultSet.next()) {
            ObservableList<String> row = FXCollections.observableArrayList();
            for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) {
                row.add(resultSet.getString(i));
            }
            data.add(row);
        }
        tableView.setItems(data);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...