Creating flashing table cell in JavaFX 8

In my current project with JavaFX, we need cells to flash when their value has been updated so that a user would notice the change. Although this sounds like an easy piece of code to write, it took three tries to get this right.

The first versions that I wrote used CSS manipulation and timer which updated the opacity value. This created a huge overhead since CSS handling in JavaFX is not effective and should be avoided in cell updateItem method if possible.

Eventually, I ended up with a solution that uses StackPane with BorderPane as a background and FadeTransition to handle the animation. Hopefully it helps if you are building something similar.

Conversation and examples can be found from Oracle forum:


import java.util.Comparator;

import javafx.animation.FadeTransition;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.util.Duration;


 * @author jaakkju
 * @param <S>
 * @param <T>
public class FlashingTableCell<S, T> extends TableCell<S, T> {

    private static final Color INCREASE_HIGHLIGHT_COLOR = Color.rgb(0, 255, 0, 0.8);
    private static final Color DECREASE_HIGHLIGHT_COLOR = Color.rgb(255, 0, 0, 0.8);
    private static final Color HIGHLIGHT_COLOR = Color.rgb(255, 255, 0, 0.8);
    private static final Duration HIGHLIGHT_TIME = Duration.millis(300);
    private final Background bgIncrease = new Background(new BackgroundFill(INCREASE_HIGHLIGHT_COLOR, CornerRadii.EMPTY, Insets.EMPTY));
    private final Background bgDecrease = new Background(new BackgroundFill(DECREASE_HIGHLIGHT_COLOR, CornerRadii.EMPTY, Insets.EMPTY));
    private final Background bgChange = new Background(new BackgroundFill(HIGHLIGHT_COLOR, CornerRadii.EMPTY, Insets.EMPTY));

    private final BorderPane background = new BorderPane();
    private final LabeledText lblText = new LabeledText(this);
    private final FadeTransition animation = new FadeTransition(HIGHLIGHT_TIME, background);

    private final StackPane container = new StackPane();

    private T prevValue;
    private S prevItem;

    final private Comparator<T> comparator;

    public FlashingTableCell(Comparator<T> comparator, Pos alignment) {
        this.comparator = comparator;


        container.getChildren().addAll(background, lblText);

    protected void updateItem(T value, boolean empty) {
        super.updateItem(value, empty);

        S currentItem = getTableRow() != null && getTableRow().getItem() != null ? (S) getTableRow().getItem() : null;

         * We check that the value has been updated and that the row model/item
         * under the cell is the same. JavaFX table reuses cells so item is not
         * always the same!
        boolean valueChanged = (prevValue == null && value != null)
                || (value != null && (prevValue.hashCode() != value.hashCode()));
        boolean sameItem = currentItem != null && prevItem != null && currentItem == prevItem;

        if (valueChanged && sameItem) {

            if (comparator != null) {
                int compare =, prevValue);
                if (compare > 0) {
                } else if (compare < 0) {
            } else {


        prevValue = value;
        prevItem = currentItem;