JavaFX自定义ListCell

时间:2017-04-20 15:16:35

标签: javafx-8

我正试图在ListCell出现时设置动画。 特别是我尝试在刚刚添加到列表中时为新单元设置动画。 现在它工作得很好,除非我滚动ListView,然后索引搞砸了,错误的单元格动画。 我在项目模型中使用布尔标志(输入)来检测单元格何时用于全新项目。

    public class TimeListCell extends ListCell<MarkItem> {

    private static final String BUTTON_GOTO_MARK_CLASS = "but-markgoto";
    private static final String LABEL_TIME_MARK_CLASS = "track-time";
    private static final String BUTTON_DELETE_MARK_CLASS = "but-markdel";
    private static final String MARK_HIGHLIGHT_CURRENT_CLASS = "highlighted";

    private Instant time;

    private MarkItem markItem;

    protected ListCellAnimation anim;

    private HBox root = new HBox();
    private Button go = new Button();
    private Label track = new Label();;
    private Button del = new Button();

    private ChangeListener<? super Boolean> highlightChange = (e, o, n) -> { setHighlighted(n); };

    public TimeListCell (Consumer<MarkItem> onGoto, Consumer<MarkItem> onDelete) {

        root.setAlignment(Pos.CENTER);

        go.getStyleClass().add(BUTTON_GOTO_MARK_CLASS);
        go.setOnAction( e -> {
            if (onGoto != null) {
                // Trigger GOTO consumer function
                onGoto.accept(markItem);
            }
        });
        track.getStyleClass().add(LABEL_TIME_MARK_CLASS);
        del.getStyleClass().add(BUTTON_DELETE_MARK_CLASS);
        del.setOnAction( e -> {
            // First trigger exit animation then delete item
            this.animateExit(onDelete);
        });

        root.getChildren().add(go);
        root.getChildren().add(track);
        root.getChildren().add(del);

    }

    @Override
    protected void updateItem (final MarkItem item, boolean empty) {

        super.updateItem(item, empty);

        if (markItem != null) {
            markItem.highlightedProperty().removeListener(highlightChange);
        }

        if (!empty && item != null) {
            markItem = item;
            time = item.getTime();

            track.setText(DateUtil.format(time, DateUtil.Pattern.TIME));
            setGraphic(root);

            item.highlightedProperty().addListener(highlightChange);
            setHighlighted(item.isHighlighted());

            if (anim == null) {
                //Adding Animation to the ListCell
                anim = new ListCellAnimation(this);
                //KeyFrame[] f = getKeyFrames(types);
                KeyFrame[] frames = null;
                if (anim.getKeyFrames().size() == 0) {
                    KeyFrame[] f = anim.getPopIn(frames);
                    if (f != null) {
                        anim.getKeyFrames().addAll(f);
                    }
                }
            }

            if (item.isEntering()) {
                //Checking when to play Animation
                animateEnter();
                item.setEntering(false);
            }
        } else {
            setGraphic(null);
        }
    }

    /**
     * Set/unset cell highlighted style for display.
     *
     * @param   highlighted
     *              Whether or not to highlight the cell
     */
    public void setHighlighted (boolean highlighted) {

        track.getStyleClass().remove(MARK_HIGHLIGHT_CURRENT_CLASS);
        if (highlighted)
            track.getStyleClass().add(MARK_HIGHLIGHT_CURRENT_CLASS);
    }

    /**
     * Animate entering cell.
     */
    private void animateEnter() {
            if (anim != null && anim.getKeyFrames().size() >= 0
                    && (anim.getTimeline().getStatus() == Timeline.Status.STOPPED
                    || anim.getTimeline().getStatus() == Timeline.Status.PAUSED)) {
                    anim.getTimeline().playFromStart();
            }
    }

    /**
     * Animate exiting cell.
     * Trigger DELETE consumer function when animation is complete.
     */
    private void animateExit (Consumer<MarkItem> onDelete) {

        anim.getReversedTimeline().setOnFinished( t -> {
            // Remove item from list
            if (onDelete != null) {
                onDelete.accept(markItem);
            }
            // Prepare cell for next item to use it
            scaleXProperty().set(1);
            scaleYProperty().set(1);
            });
        anim.getReversedTimeline().playFromStart();
    }

    public Instant getTime () {

        return time;
    }
}

有没有人知道什么可能搞乱细胞索引? 感谢。

1 个答案:

答案 0 :(得分:0)

如果重复使用动画的单元格来显示不是&#34;输入&#34;的项目,则需要停止当前动画:

    if (item.isEntering()) {
        //Checking when to play Animation
        animateEnter();
        item.setEntering(false);
    } else {
        anim.getTimeline().stop();
    }

通常,您似乎假设任何给定的单元格仅用于单个项目,当然不是这种情况。您的代码中可能存在其他错误,这是此假设的结果,但这是我能看到的主要错误。