Получить графику TableCell

Я реализовал пользовательский TableCell и TableColumn, чтобы показать гиперссылку, пока ячейка не редактируется. Я хочу добавить событие setOnAction для гиперссылки. Поскольку я хочу повторно использовать TableCell, я не могу добавить код в метод updateItem TableCell. Есть ли способ реализовать это?

public class TableColumnHyperlink<S> extends TableColumn<S, String> {

    public TableColumnHyperlink (String header) {
        super(header);
        Callback<TableColumn<S, String>, TableCell<S, String>> hypCellFactory =
            (TableColumn<S, String> p) -> new TableCellHyperlink();

        setCellFactory(hypCellFactory);
    }
}

И реализация TableCell

public class TableCellHyperlink<S> extends TableCell<S, String> {

    private final TextField textField;
    private final Hyperlink hyperlink;

    public TableCellHyperlink() {

        textField = new TextField();
        hyperlink = new Hyperlink();
        setAlignment(Pos.CENTER_LEFT);
    }

    @Override
    public void startEdit() {
        super.startEdit();
        createTextField();
        setText(null);
        setGraphic(textField);
        textField.requestFocus();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setText(getItem());
        setGraphic(null);
    }

    @Override
    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty && (getTableRow() == null ? true : getTableRow().isEmpty()));
        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            if(isEditing()) {
                setText(getString());
                setGraphic(textField);
            } else {
                setText(null);
                hyperlink.setText(getString());
                setGraphic(hyperlink);
            }
        }
    }


    private void createTextField() {
        textField.setText(getString());
        textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);

        textField.addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent t) -> {
            if (t.getCode() == KeyCode.ENTER) {
                commitEdit(textField.getText());
            } else if (t.getCode() == KeyCode.ESCAPE) {
                cancelEdit();
            }
        });
    }

    private String getString() {
        return (getItem() != null)?getItem():"";
    }
}

введите здесь описание изображения


person Sudip Saha    schedule 13.05.2014    source источник
comment
Не совсем уверен, в чем вопрос. Вы можете просто сделать hyperlink.setOnAction( event -> ...); в конструкторе TableCellHyperlink. Но я думаю, что упускаю проблему...?   -  person James_D    schedule 14.05.2014
comment
да Джеймс_Д. Поскольку я хочу повторно использовать TableCellHyperlink в нескольких TableView, поведение гиперссылки каждый раз будет разным. Установка hyperlink.setOnAction внутри TableCellHyperlink не сделает класс универсальным.   -  person Sudip Saha    schedule 14.05.2014


Ответы (1)


Если реализация обработчика событий зависит от экземпляра, вам необходимо передать обработчик событий (или функцию) в конструктор. Поскольку вам, вероятно, потребуется доступ к ячейке, вы сделаете что-то вроде

public class TableCellHyperlink<S> extends TableCell<S, String> {

    private final TextField textField;
    private final Hyperlink hyperlink;


    public TableCellHyperlink(Consumer<TableCellHyperlink<S> handlerFunction) {

        textField = new TextField();
        hyperlink = new Hyperlink();
        hyperlink.setOnAction(event -> handlerFunction.accept(this));
        setAlignment(Pos.CENTER_LEFT);
    }

    // ...
}

Теперь вы можете сделать что-то вроде

TableCellHyperlink<MyType> hyperlinkCell = new TableCellHyperlink<>(cell -> {
    MyType rowValue = (MyType) cell.getTableRow().getValue(); // getTableRow() returns TableRow, not TableRow<MyType>
    String cellValue = cell.getItem();
    // implement action
});

Очевидно, вы можете переместить параметр вверх и передать его в пользовательский конструктор TableColumn, если хотите.

person James_D    schedule 14.05.2014