Как сделать универсальный рендерер TableColumn для столбца JavaFX TableView

Позвольте мне скопировать предложение и примечание из ISO-32000-2. Этот документ еще не доступен, потому что он будет выпущен только в 2016 году. Однако это очень ясно по вопросу этого вопроса:

enter image description here [/g0]

Однако это всегда было правдой: оно было зафиксировано только в документации, принадлежащей Adobe. Начиная с версии 2.0, он будет нормативным.

Короче: вы просите что-то, что нарушает спецификацию PDF.

0
задан fabian 16 January 2019 в 10:53
поделиться

1 ответ

Единственный способ «передать метод» - создать объект, содержащий логику для этого, или использовать ссылку на метод.

Более того, даже несмотря на то, что JavaFX не применяет эти ограничения, id должен быть уникальным. Вместо этого используйте псевдоклассы.

Вы можете использовать

private static final PseudoClass ZERO = PseudoClass.getPseudoClass("zero-atm");
private static final PseudoClass CREDIT = PseudoClass.getPseudoClass("credit-atm");
private static final PseudoClass DEBIT = PseudoClass.getPseudoClass("debit-atm");

public static <S, T> void renderColumn(TableColumn<S, T> column,
        final Callback<? super S, ObservableValue<T>> extractor, final Callback<? super T, String> converter,
        final Comparator<T> comparator, final T zero) {
    if (extractor == null || comparator == null || zero == null) {
        throw new IllegalArgumentException();
    }

    column.setCellValueFactory(cd -> extractor.call(cd.getValue()));
    column.setCellFactory(col -> new TableCell<S, T>() {
        @Override
        protected void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);

            pseudoClassStateChanged(ZERO, false);
            pseudoClassStateChanged(CREDIT, false);
            pseudoClassStateChanged(DEBIT, false);

            if (empty || item == null) {
                setText("");
            } else {
                setText(converter.call(item));
                int comparison = comparator.compare(zero, item);
                if (comparison == 0) {
                    pseudoClassStateChanged(ZERO, true);
                } else {
                    pseudoClassStateChanged(comparison < 0 ? CREDIT : DEBIT, true);
                }
            }
        }
    });
}

public static <S, T extends Comparable<T>> void renderColumn(TableColumn<S, T> column,
        Callback<? super S, ObservableValue<T>> extractor, Callback<? super T, String> converter, T zero) {
    renderColumn(column, extractor, converter, Comparator.naturalOrder(), zero);
}

. Предполагая, что вы измените тип budget на ObjectProperty<BigDecimal>, метод может быть вызван, как показано ниже. (BigDecimal намного проще работать, когда речь идет о сравнении значений и выполнении других математических операций в дополнение к избежанию ошибок округления.) В противном случае вы можете просто жестко закодировать параметр второго типа и другие функциональные возможности и оставить только первые 2 параметра метода.

renderColumn(column, TxnObject::budgetAmountProperty, (BigDecimal val) -> val.abs().toString(), BigDecimal.ZERO);
0
ответ дан fabian 16 January 2019 в 10:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: