我有2组事件可以更改表行的外观。

  • 表在某些情况下闪烁
  • 表在添加新项目时突出显示

  • 假设我的TableView称为table,我的代码结构如下:
    TableView<Trade> table = ... ;
    table.setRowFactory(            private final BooleanBinding itemIsNewTrade = Bindings.isNotNull(itemProperty()).and(Bindings.equal(itemProperty(), recentlyAddedTrade));
    
            {
                // anonymous constructor:
                itemIsNewTrade.addListener((obs, wasNew, isNew) -> pseudoClassStateChanged(newTradePseudoClass, isNew));
            }
    
                tv -> {
                TableRow<Trade> row = new TableRow<>();
                Timeline flasher = new Timeline(
    
                        new KeyFrame(Duration.seconds(0.5), e -> {
                            row.pseudoClassStateChanged(flashHighlight, true);
                        }),
    
                        new KeyFrame(Duration.seconds(1.0), e -> {
                            row.pseudoClassStateChanged(flashHighlight, false);
                        })
                );
                flasher.setCycleCount(Animation.INDEFINITE);
    
                ChangeListener<Boolean> cautionListener = (obs, cautionWasSet, cautionIsNowSet) -> {
                    if (cautionIsNowSet) {
                        flasher.play();
                    } else {
                        flasher.stop();
                        row.pseudoClassStateChanged(flashHighlight, false);
                    }
                };
    
                row.itemProperty().addListener((obs, oldItem, newItem) -> {
                    if (oldItem != null) {
                        oldItem.cautionProperty().removeListener(cautionListener);
                    }
                    if (newItem == null) {
                        flasher.stop();
                        row.pseudoClassStateChanged(flashHighlight, false);
                    } else {
                        newItem.cautionProperty().addListener(cautionListener);
                        if (newItem.cautionProperty().get()) {
                            flasher.play();
                        } else {
                            flasher.stop();
                            row.pseudoClassStateChanged(flashHighlight, false);
                        }
                    }
                });
                return row ;
            }
        );
    

    更新:
    用于表格刷新的代码来自here,而用于表格突出显示的代码来自here。我试图通过具有上述结构将两者结合在一起。

    但是我出错了。我只是不知道如何将匿名内部类和lambda表达式结合在一起

    我应该如何克服呢?

    最佳答案

    最好的方法是创建一个单独的TableRow类,而不是一个匿名内部类。

    我在下面创建了一个示例实现。

    一些值得一提的事情:

  • 您需要在CSS文件中为新添加的.table-row-cell:new定义样式TableRow
  • 您需要在CSS文件中为当前正在闪烁的.table-row-cell:flash定义样式TableRow
  • 构造函数需要知道(ObjectExpression)最近添加的项的存储位置,在您的情况下可能是recentlyAddedTrade
  • 构造函数需要知道(Function<T, BooleanExpression>)如何提取确定闪烁状态的属性。在您的情况下,应为Trade::cautionProperty

  • 这是示例实现:
    public static class AnimatedTableRow<T> extends TableRow<T> {
    
        private static final PseudoClass PS_NEW = PseudoClass.getPseudoClass("new");
        private static final PseudoClass PS_FLASH = PseudoClass.getPseudoClass("flash");
    
        private final ObjectExpression<T> recentItem;
        private final InvalidationListener recentlyAddedListener = fObs -> recentItemChanged();
    
        private final Function<T, BooleanExpression> flashExtractor;
        private final ChangeListener<Boolean> flashListener = (fObs, fOld, fNew) -> flasherChanged(fNew);
        private final Timeline flashTimeline;
    
        public AnimatedTableRow(ObjectExpression<T> fRecentlyAddedProperty,
                Function<T, BooleanExpression> fFlashExtractor) {
            recentItem = fRecentlyAddedProperty;
            recentItem.addListener(new WeakInvalidationListener(recentlyAddedListener));
    
            flashExtractor = fFlashExtractor;
            flashTimeline = new Timeline(
                    new KeyFrame(Duration.seconds(0.5), e -> pseudoClassStateChanged(PS_FLASH, true)),
                    new KeyFrame(Duration.seconds(1.0), e -> pseudoClassStateChanged(PS_FLASH, false)));
            flashTimeline.setCycleCount(Animation.INDEFINITE);
        }
    
        private void flasherChanged(boolean fNew) {
            if (fNew) {
                flashTimeline.play();
            } else {
                flashTimeline.stop();
                pseudoClassStateChanged(PS_FLASH, false);
            }
        }
    
        private void recentItemChanged() {
            final T tmpRecentItem = recentItem.get();
            pseudoClassStateChanged(PS_NEW, tmpRecentItem != null && tmpRecentItem == getItem());
        }
    
        @Override
        protected void updateItem(T item, boolean empty) {
            if (getItem() != null) {
                final BooleanExpression be = flashExtractor.apply(getItem());
                if (be != null) {
                    be.removeListener(flashListener);
                }
            }
    
            super.updateItem(item, empty);
    
            if (getItem() != null) {
                final BooleanExpression be = flashExtractor.apply(getItem());
                if (be != null) {
                    be.addListener(flashListener);
                    flasherChanged(be.get());
                }
            }
    
            recentItemChanged();
        }
    }
    

    用法:
    table.setRowFactory(tableView -> new AnimatedTableRow<>(recentlyAddedPerson, Person::flashProperty));
    

    09-27 09:30