通过javafx中的自定义单元工厂淡化过渡

时间:2016-09-08 19:57:11

标签: css javafx

我在javafx中使用自定义单元工厂根据警报状态设置单元格样式,该状态基于现在的时间和检查时间。

一切正常,但我也希望添加一个淡入淡出过渡或其他东西,这将使行基本上闪烁,直到通过更改检查时间来确认。

它比我想要添加大量代码要复杂一些,所以我将发布我的单元工厂类

public class FormattedTableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
    private TableCell<S, T> cell = null;
    private FadeTransition ft;

    public FormattedTableCellFactory() {
    }

    @Override
    public TableCell<S, T> call(TableColumn<S, T> p) {
        cell = new TableCell<S, T>() {
            @Override
            protected void updateItem(Object item, boolean empty) {
                super.updateItem((T) item, empty);

                // CSS Styles
                String cssStyle;

                Person person = null;

                if(getTableRow() != null ) {
                    person = (Person) getTableRow().getItem();
                }

                ft = new FadeTransition(Duration.millis(500), cell);
                ft.setFromValue(1.0);
                ft.setToValue(0.1);
                ft.setCycleCount(Timeline.INDEFINITE);
                ft.setAutoReverse(true);
                //Remove all previously assigned CSS styles from the cell.



                //Determine how to format the cell based on the status of the container.

                if(person != null){
                    switch(PersonAlert.getAlert(person)){
                        case WARNING:
                            ft.stop();
                            cssStyle = "warning";
                            break;
                        case PAST_DUE:
                            ft.stop();
                            cssStyle = "pastdue";
                            break;
                        case ERC_PAST_DUE:
                            ft.stop();
                            cssStyle = "ercpastdue";
                            break;
                        case OVERDUE:
                            ft.playFromStart();
                            cssStyle = "overdue";
                            break;
                        case OVERNIGHT:
                            ft.stop();
                            cssStyle = "overnight";
                            break;
                        default:
                            ft.stop();
                            cssStyle = "normal";
                            break;
                    }
                }else{
                    ft.stop();
                    setText("");
                    return;
                }

                //Set the CSS style on the cell and set the cell's text.
                getStyleClass().setAll(cssStyle);
                if(item != null) {
                    setText(item.toString());
                }else{
                    setText("");
                }
            }
        };
        return cell;
    }
}

此代码正常工作,只要此人具有特定状态,单元格的颜色将适当更改。这里唯一的问题是淡入淡出过渡,无论何时第一次运行,淡入淡出过渡运行正常,但当它变为不同的样式时,它不会停止并保持闪烁。

我无法让淡入淡出过渡停止。我相信这是因为每次调用此updateItem时,它都会创建一个我的淡入淡出过渡的新实例,因此当它调用stop时,它会在当前过渡而不是前一个过渡时调用它。我试图通过初始化顶部的过渡来消除这种情况,但它甚至不会闪烁。

所以我的问题是,如何在调用停止时编辑这个以使淡入淡出过渡停止,或者是否有一种不同的方法可以使用单元工厂使单元格/行“闪烁”?

1 个答案:

答案 0 :(得分:0)

你把事情放在了错误的水平。

每个单元格应该有一个淡入淡出过渡。目前,每次在单元格上调用 updateItem()时,都会创建一个新的淡入淡出过渡。您为整个工厂保留一个参考(只需一个参考,无论创建多少个单元格),这只会参考最近创建的淡入淡出过渡。

您同样在工厂中保留了对最近创建的单元格的引用,但出于某种原因,(可能很幸运)您从未实际使用它。

还有一些需要注意的事项:调用getStyleClass().setAll(...)并不是一个好主意,因为这会删除单元格中的所有默认样式类(例如.table-cell),这可能会产生影响删除所有默认样式处理。样式类有点难以处理,因为它们是作为列表实现的,但是你应该删除所有出现的那些你不想明确的那些,并确保你不添加你想要的那些副本(除非你真的打算这样做)。此外,您假设(通过强制转换)表视图的类型为Person,因此将行类型设为通用没有意义。

所以,虽然我不可能测试,因为你没有提供任何代码来测试,你可能想要这些内容:

import java.util.Arrays;
import java.util.List;

import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
import javafx.util.Duration;

public class FormattedTableCellFactory<T> implements Callback<TableColumn<Person, T>, TableCell<Person, T>> {

    private static final List<String> ALL_STYLES = Arrays.asList(
        "warning", "pastdue", "ercpastdue", "overnight", "normal"
    );

    @Override
    public TableCell<Person, T> call(TableColumn<Person, T> p) {
        TableCell<Person, T> cell = new TableCell<Person, T>() {

            private FadeTransition ft ;

            {
                ft = new FadeTransition(Duration.millis(500), this);
                ft.setFromValue(1.0);   
                ft.setToValue(0.1);   
                ft.setCycleCount(Timeline.INDEFINITE);   
                ft.setAutoReverse(true);  
            }

            @Override
            protected void updateItem(T item, boolean empty) {
                super.updateItem(item, empty);

                // CSS Styles
                String cssStyle = "";

                Person person = null;

                if(! isEmpty() ) {
                    // avoid casting here, if you prefer:
                    person = getTableView().getItems().get(getIndex());
                }

                //Remove all previously assigned CSS styles from the cell.

                getStyleClass().removeAll(ALL_STYLES);


                //Determine how to format the cell based on the status of the container.

                if(person != null){
                    switch(PersonAlert.getAlert(person)){
                        case WARNING:
                            ft.stop();
                            setOpacity(1.0);
                            cssStyle = "warning";
                            break;
                        case PAST_DUE:
                            ft.stop();
                            setOpacity(1.0);
                            cssStyle = "pastdue";
                            break;
                        case ERC_PAST_DUE:
                            ft.stop();
                            setOpacity(1.0);
                            cssStyle = "ercpastdue";
                            break;
                        case OVERDUE:
                            ft.playFromStart();
                            cssStyle = "overdue";
                            break;
                        case OVERNIGHT:
                            ft.stop();
                            setOpacity(1.0);
                            cssStyle = "overnight";
                            break;
                        default:
                            ft.stop();
                            setOpacity(1.0);
                            cssStyle = "normal";
                            break;
                    }
                }else{
                    ft.stop();
                    setOpacity(1.0);
                    setText("");
                }

                //Set the CSS style on the cell and set the cell's text.
                if(item != null) {
                    getStyleClass().add(cssStyle);
                    setText(item.toString());
                }else{
                    setText("");
                }
            }
        };
        return cell;
    }


}