Как добавить EventHandler для всех ячеек в TableView, не создавая новую CellFactory для каждого столбца? - PullRequest
0 голосов
/ 04 мая 2019

Я пытаюсь позволить пользователю щелкнуть средней кнопкой мыши по любой ячейке в TableView и скопировать ее текст в системный буфер обмена.Тем не менее, я не могу понять, как пройти через все ячейки в TableView.

Есть ли способ получить List из всех TableCells встрока или столбец, чтобы я мог применить к ним метод setOnMouseClicked()?

Я понимаю, что это легко сделать с помощью CellFactory;но у меня уже есть несколько пользовательских фабрик, примененных к некоторым столбцам, и мне нужно избегать их переопределения или создания 20+ фабрик ячеек для остальных столбцов.

Вот MCVE:

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.text.NumberFormat;

public class TableCellClickListener extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // Simple Interface
        VBox root = new VBox(10);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(10));

        TableView<Person> tableView = new TableView<>();

        TableColumn<Person, String> colName = new TableColumn<>("Name");
        colName.setCellValueFactory(tf -> tf.getValue().nameProperty());

        TableColumn<Person, Number> colBalance = new TableColumn<>("Balance");
        colBalance.setCellValueFactory(tf -> tf.getValue().balanceProperty());

        tableView.getColumns().addAll(colName, colBalance);

        // Format the balance column
        colBalance.setCellFactory(t -> new TableCell<Person, Number>() {
            @Override
            protected void updateItem(Number item, boolean empty) {
                super.updateItem(item, empty);
                if (empty) {
                    setText(null);
                } else {
                    setText(NumberFormat.getCurrencyInstance().format(item));
                }
            }
        });

        // This is where I am stuck; is there such a list of cells in the API?
        for (TableCell cell : listOfCells) {
            setCopyListener(cell);
        }

        // Show the stage
        primaryStage.setScene(new Scene(root));
        primaryStage.setTitle("Sample");
        primaryStage.show();
    }

    private void setCopyListener(TableCell cell) {
        cell.setOnMouseClicked(event -> {
            if (!cell.isEmpty() && event.getButton().equals(MouseButton.MIDDLE)) {
                System.out.println(cell.getText());
            }
        });
    }
}

class Person {

    private final StringProperty name = new SimpleStringProperty();
    private final DoubleProperty balance = new SimpleDoubleProperty();

    public Person(String name, double balance) {
        this.name.set(name);
        this.balance.set(balance);
    }

    public String getName() {
        return name.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public StringProperty nameProperty() {
        return name;
    }

    public double getBalance() {
        return balance.get();
    }

    public void setBalance(double balance) {
        this.balance.set(balance);
    }

    public DoubleProperty balanceProperty() {
        return balance;
    }
}

У меня есть готовый метод setCopyListener(TableCell cell), но я не могу найти способ перебрать все ячейки без CellFactory для каждого столбца.Я просмотрел документацию по Java и не могу найти способ доступа к списку всех ячеек в строке или столбце.

Я скучаю по нему?

1 Ответ

0 голосов
/ 04 мая 2019

Ячейки создаются скином, и они не будут доступны до первого прохода макета. Кроме того, изменение размера TableView может привести к созданию дополнительных ячеек. Либо вы создаете пользовательский скин для TableView, либо используете тот факт, что MouseEvent предоставляет свойство pickResult, которое содержит узел под мышью в ваших интересах.

Примечание. Узел, содержащийся в pickResult, может быть потомком TableCell или вообще не быть частью ячейки (например, заголовок столбца или полоса прокрутки). Вам нужно перебирать иерархию узлов, пока вы не найдете ячейку или TableView.

tableView.addEventHandler(MouseEvent.MOUSE_CLICKED, evt -> {
    if (evt.getButton() == MouseButton.MIDDLE) {
        TableCell<Person, ?> cell = findCell(evt, tableView);
        if (cell != null && !cell.isEmpty()) {
            System.out.println(cell.getText());
            evt.comsume();
        }
    }
});
private static <T> TableCell<T, ?> findCell(MouseEvent event, TableView<T> table) {
    Node node = event.getPickResult().getIntersectedNode();

    // go up in node hierarchy until a cell is found or we can be sure no cell was clicked
    while (node != table && !(node instanceof TableCell)) {
        node = node.getParent();
    }
    return node instanceof TableCell ? (TableCell<T, ?>) node : null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...