javafx:setRowFactory中的多个事件,并结合了匿名内部类和lambda表达式 [英] javafx: Multiple events in a setRowFactory and combining anonymous inner class and lambda expressions

查看:492
本文介绍了javafx:setRowFactory中的多个事件,并结合了匿名内部类和lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两组事件可以改变表格行的外观。


  1. 当某些条件闪烁时表格闪烁

  2. 表格突出显示添加新项目时

假设我的 TableView 被称为 table ,我的代码结构是这样的:

  TableView< Trade> table = ...; 
table.setRowFactory(private final BooleanBinding itemIsNewTrade = Bindings.isNotNull(itemProperty())。and(Bindings.equal(itemProperty(),recentAddedTrade));

{
/ /匿名构造函数:
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);
}),

新KeyFrame(Duration.seconds(1.0),e - > {
row.pseudoClassStateChanged( flashHighlight,false);
})
);
flasher.setCycleCount(Animation.INDEFINITE);

的ChangeListener<布尔> 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);
}
}
});
返回行;
}
);

更新:
表格闪烁的代码来自< a href =https://stackoverflow.com/questions/32164454/javafx-table-row-flashing/32168257#32168257>这里,而表突出显示的代码来自here 。我尝试通过具有上述结构将两者结合在一起。



但是我收到了错误。我只是不知道如何将Anonymous内部类和lambda表达式结合在一起



我应该如何克服这个问题?

解决方案

最好的方法是创建一个单独的 TableRow 类而不是匿名内部我在下面创建了一个示例实现。



值得一提的是:


  1. 您需要在CSS文件中为新定义样式 .table-row-cell:new 添加 TableRow

  2. 您需要定义样式 .table-row-cell:flash 在你的CSS文件中,当前正在闪烁的 TableRow (s)。

  3. 构造函数需要知道( ObjectExpression )存储最近添加的项目,在您的情况下可能是 recentAddedTrade

  4. 构造函数需要知道( Function< T,BooleanExpression& gt; )如何提取确定闪烁状态的属性。在你的情况下它应该是 Trade :: cautionProperty

这是示例实现:

  public static class AnimatedTableRow< T>扩展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 recentAddedListener = fObs - > recentItemChanged();

private final函数< T,BooleanExpression> flashExtractor;
private final ChangeListener< Boolean> flashListener =(fObs,fOld,fNew) - > flasherChanged(fNew);
私人最终时间线flashTimeline;

public AnimatedTableRow(ObjectExpression< T> fRecentlyAddedProperty,
Function< T,BooleanExpression> fFlashExtractor){
recentItem = fRecentlyAddedProperty;
recentItem.addListener(new WeakInvalidationListener(recentAddedListener));

flashExtractor = fFlashExtractor;
flashTimeline =新时间轴(
新KeyFrame(Duration.seconds(0.5),e - > pseudoClassStateChanged(PS_FLASH,true)),
新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<>(recentAddedPerson,Person :: flashProperty)); 


I have 2 sets of events that change the appearance of the table row.

  1. table flashing when some conditions flash
  2. table highlighting when a new item is added

Suppose my TableView is called table, my code structure is like this:

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 ;
        }
    );

UPDATE: The code for table flashing comes from here, while the code for table highlighting comes from here. I tried to combine both together by having a structure like above.

But I am getting error. I just do not know how to combine Anonymous inner class and lambda expression together

How should I overcome this ?

解决方案

The best way to do this, is to create a separate TableRow class instead of an anonymous inner class.

I created an example implementation below.

Some things worth mentioning:

  1. You need do define the style .table-row-cell:new in your CSS file for the newly added TableRow.
  2. You need to define the style .table-row-cell:flash in your CSS file for the TableRow(s) which are currently flashing.
  3. The constructor needs to know (ObjectExpression) where the recently added item is stored, which is probably recentlyAddedTrade in your case.
  4. The constructor needs to know (Function<T, BooleanExpression>) how to extract the property determining the flashing state. In your case it should be Trade::cautionProperty.

Here is the example implementation:

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();
    }
}

Usage:

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

这篇关于javafx:setRowFactory中的多个事件,并结合了匿名内部类和lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆