【问题标题】:Fade Transition via custom cell factory in javafx通过 javafx 中的自定义单元工厂淡化过渡
【发布时间】:2016-09-08 19:57:11
【问题描述】:

我在 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 时停止淡入淡出过渡,或者是否有其他方法可以使用单元工厂使单元格/行“闪烁”?

【问题讨论】:

    标签: css javafx


    【解决方案1】:

    您在错误的级别上界定了范围。

    每个单元格都应该有一个淡入淡出过渡。目前,您每次在单元格上调用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;
        }
    
    
    }
    

    【讨论】:

    • 是的!这正是我想要的。我知道我错误地创建了淡入淡出过渡,但我不知道如何正确地做到这一点。非常感谢。
    • 如果您只是创建独立类作为单元实现,然后在列上设置单元工厂时使用 lambda 表达式,这可能也会好得多。 IE。定义public class FormattedTableCell&lt;T&gt; extends TableCell&lt;Person, T&gt; { ...},然后当你使用它时,只需执行someColumn.setCellFactory(p -&gt; new FormattedTableCell&lt;String&gt;());(或该列的任何类型)。至少,它会节省两级缩进...
    • 我在 fxml 中设置 cellFactory。我不确定这是否会改变任何事情。
    • 要在 FXML 中设置单元工厂,您确实需要一个实现回调的类。
    • 好的。非常感谢。
    猜你喜欢
    • 2016-04-22
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-18
    • 2020-04-13
    • 1970-01-01
    • 2020-09-29
    相关资源
    最近更新 更多