JavaFX动画问题

标签 java animation javafx

我目前正在使用 JavaFX 开发一个带有动画的应用程序。该应用程序由人工校正员使用,校正计算机生成的字幕。动画中有一个 float 文本。我的问题是动画有时会关闭。您可以看下面的图片进行演示:

enter image description here

此缺陷主要发生在调整大小之后。当动画中断时,它永远不会再次达到完全运行的状态。 我使用插入 Swing UI 中的 JFXpanel。我这样使用它是因为我在 Swing 中创建了相当多的代码,并且我不想将它们全部扔掉。我不使用 Swing 制作动画,因为我无法创建足够流畅的动画。 这是动画相关的代码:

public class AnimationPanel extends JFXPanel {

    public MyAnimationTimer animationTimer;
    public EditObject editObject;

    public Color colorHOST1;
    public Color colorHOST2;
    public Color colorGUEST1;
    public Color colorGUEST2;
    public Color colorUSER;
    public Color colorSIGNING;

    public Color basicColor = Color.WHITE;

    public Color currentColor = Color.WHITE;

    public AnimationPanel(EditObject editObject) {
        super();

        this.editObject = editObject;

        Group group = new Group();

        this.animationTimer = new MyAnimationTimer((List<MyText>)(List<?>)group.getChildren(), this);

        final Scene scene = new Scene(group, 800, 600, Color.BLACK);

        this.setScene(scene);

        this.animationTimer.start();

/*        // Update animation when component is resized
        this.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                animationTimer.updateAnimations();
            }

            @Override
            public void componentMoved(ComponentEvent e) {
            }

            @Override
            public void componentShown(ComponentEvent e) {
            }

            @Override
            public void componentHidden(ComponentEvent e) {
            }
        });*/

    }

    public void setColors(Gui g) {
        this.colorHOST1 = Color.rgb(g.colorHOST1.getRed(), g.colorHOST1.getGreen(), g.colorHOST1.getBlue(), g.colorHOST1.getAlpha()/255.0);
        this.colorHOST2 = Color.rgb(g.colorHOST2.getRed(), g.colorHOST2.getGreen(), g.colorHOST2.getBlue(), g.colorHOST2.getAlpha()/255.0);
        this.colorGUEST1 = Color.rgb(g.colorGUEST1.getRed(), g.colorGUEST1.getGreen(), g.colorGUEST1.getBlue(), g.colorGUEST1.getAlpha()/255.0);
        this.colorGUEST2 = Color.rgb(g.colorGUEST2.getRed(), g.colorGUEST2.getGreen(), g.colorGUEST2.getBlue(), g.colorGUEST2.getAlpha()/255.0);
        this.colorUSER = Color.rgb(g.colorUSER.getRed(), g.colorUSER.getGreen(), g.colorUSER.getBlue(), g.colorUSER.getAlpha()/255.0);
        this.colorSIGNING = Color.rgb(g.colorSIGNING.getRed(), g.colorSIGNING.getGreen(), g.colorSIGNING.getBlue(), g.colorSIGNING.getAlpha()/255.0);

    }
}



public class MyAnimationTimer extends AnimationTimer {
    private List<MyText> nodes;
    private long subtitle_max_time_in_app;
    private AnimationPanel animationPanel;
    private boolean stopAtTheEnd = false;
    private boolean isAtTheEnd = false;
    private int currentPos = 0;

    public MyAnimationTimer(List<MyText> nodes, AnimationPanel animationPanel) {
        super();
        this.nodes = nodes;
        this.animationPanel = animationPanel;
    }

    @Override
    public void handle(long now) {
        MyText node;
        if(this.stopAtTheEnd) {
            if(this.isAtTheEnd) {
                for (int i = this.currentPos; i < this.nodes.size(); i += 2) {
                    node = nodes.get(i);
                    if(this.collides(nodes.get(i-2), node)) {
                        node.setTranslateXforTextandSubText(nodes.get(i-2).getBoundsInParent().getWidth() + nodes.get(i-2).getTranslateX() + 10);
                        this.currentPos+=2;
                    }
                    node.setTranslateXforTextandSubText(node.getTranslateX() - node.getVelocity());
                }
            } else {
                if(nodes.size()!=0) {
                    node = nodes.get(0);
                    if((node.getTranslateX() - node.getVelocity()) < 0) {
                        node.setTranslateXforTextandSubText(0);
                        this.isAtTheEnd = true;
                        this.currentPos = 2;
                    } else {
                        for (int i = 0; i < this.nodes.size(); i += 2) {
                            node = nodes.get(i);
                            node.setTranslateXforTextandSubText(node.getTranslateX() - node.getVelocity());
                        }
                    }
                }
            }
        } else {
            for (int i = 0; i < this.nodes.size(); i += 2) {
                node = nodes.get(i);
                node.setTranslateXforTextandSubText(node.getTranslateX() - node.getVelocity());
            }
        }
    }

    private boolean collides(MyText node1, MyText node2) {
        return (node1.getBoundsInParent().getWidth() + node1.getTranslateX() - node2.getTranslateX()) + 7 >= 0;
    }

    public void addNode(final MyText node) {
        Platform.runLater(() -> {
            node.setTranslateYforTextandSubText(animationPanel.getHeight() / 2);

            node.setTranslateXforTextandSubText(animationPanel.getWidth());

            node.setVelocity(this.getVelocity());
            nodes.add(node);
            nodes.add(node.id);

            // Check for overlaying
            if(nodes.size()>=4) {
                int size = nodes.size();
                double overlaying = (nodes.get(size-4).getBoundsInParent().getWidth() + nodes.get(size-4).getTranslateX() - nodes.get(size-2).getTranslateX()) + 7;
                if(overlaying>0) {
                    nodes.get(size-2).setTranslateXforTextandSubText(nodes.get(size-2).getTranslateX()+overlaying);
                }
            }
        });
    }

    public void recalculateGaps() {
        Platform.runLater(() -> {
            if (nodes.size() >= 4) {
                double overlaying;
//                System.out.println("Size: " + nodes.size());
                for (int i = nodes.size() - 2; i > 0; i -= 2) {
                    overlaying = (nodes.get(i - 2).getBoundsInParent().getWidth() + nodes.get(i - 2).getTranslateX() - nodes.get(i).getTranslateX()) + 7;
                    if (overlaying > 0) {
                        nodes.get(i - 2).setTranslateXforTextandSubText(nodes.get(i - 2).getTranslateX() - overlaying);
                    }
                }
            }
        });
    }

    public void removeNodesBehindTheScene() {
        Platform.runLater(() -> {
            MyText node;
            for (int i=0; i<nodes.size(); i+=2) {
                node = nodes.get(i);
                if(node.getTranslateX() > 0) {
                    break;
                } else {
                    if(!node.isOverdue()) {
                        animationPanel.editObject.setMessageToBeSendSoon(node);
                    }
                    nodes.remove(i);
                    nodes.remove(i);
                    i-=2;
                }
            }
        });
    }

/*    public void updateAnimations() {
//        This method is called when the window is resized.
        for (int i=0; i<this.nodes.size(); i+=2) {
            nodes.get(i).setTranslateYforTextandSubText(animationPanel.getHeight()/2);
        }
        this.setVelocity();
    }*/

    public double getVelocity() {
        return (this.animationPanel.getWidth()/4)*3/((double) this.subtitle_max_time_in_app)*1000/60;
    }

    public void setSubtitle_max_time_in_app(long subtitle_max_time_in_app) {
        this.subtitle_max_time_in_app = subtitle_max_time_in_app;
    }

    public void setStopAtTheEnd(boolean stopAtTheEnd) {
        // Remove all overdue
        if(stopAtTheEnd) {
            Platform.runLater(() -> {
                for (int i = 0; i < nodes.size(); i += 2) {
                    if (nodes.get(i).isOverdue()) {
                        nodes.remove(i);
                        // Remove ID number
                        nodes.remove(i);
                        i -= 2;
                    } else {
                        break;
                    }
                }
            });
            this.isAtTheEnd = false;
            this.currentPos = 0;
        }
        this.stopAtTheEnd = stopAtTheEnd;
    }

    public void removeUpToNode(MyText node) {
        Platform.runLater(() -> {
            if(nodes.contains(node)) {
                for (int i = 0; i < nodes.size(); i += 2) {
                    if (nodes.get(i) == node) {
                        nodes.remove(i);
                        nodes.remove(i);
                        break;
                    }
                    else {
                        nodes.remove(i);
                        nodes.remove(i);
                        i-=2;
                    }
                }
            }
        });
    }

    public void addNodesAtTheBeginning(List<MyText> nodes_list, double nodeposition) {
        Platform.runLater(() -> {
            MyText node;
            double position;
            for (int i = nodes_list.size() - 1; i >= 0; i--) {
                node = nodes_list.get(i);

                node.setTranslateYforTextandSubText(animationPanel.getHeight() / 2);

                if(nodes.size()!=0) {
                    position = this.nodes.get(0).getTranslateX() - node.getBoundsInParent().getWidth() - 10;
                } else {
                    position = animationPanel.getWidth();
                }

                if(i==(nodes_list.size() - 1)) {
                    double exactposition = nodeposition - node.getBoundsInParent().getWidth();
                    if(exactposition < position) {
                        node.setTranslateXforTextandSubText(exactposition);
                    } else {
                        node.setTranslateXforTextandSubText(position);
                    }
                } else {
                    node.setTranslateXforTextandSubText(position);
                }

                node.setVelocity(this.getVelocity());
                nodes.add(0, node.id);
                nodes.add(0, node);
            }
        });
    }
}

我测试了JavaFX的各种版本(包括JDK9中打包的版本),但没有结果。提前致谢

最佳答案

终于修复了这个bug。问题是我正在从我自己的线程而不是 JavaFX 线程设置现有节点的属性。将其放入 Platform.runLater 方法修复了它。我没有立即注意到该错误,因为它没有像尝试添加节点时那样抛出非法线程异常。我应该更彻底地红色文档。 谢谢

关于JavaFX动画问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33598060/

相关文章:

java - TIBCO 企业 3.0 架构

java - 两个对象之间共享模型

java - 如何使用 WebDriver for Java 选择动态号码链接

css - 动画无限循环

javascript - 从 setInterval 方法转移到带有 sprite 的 requestAnimationFrame

java - 将时间线或任务绑定(bind)到进度条?

java - 构造函数参数值未实现

animation - 如何在一个元素上有多个 CSS 过渡?

java - 有没有办法将 Gluon Mobile (javafxports) 与 native android 代码混合?

java - 如何使按钮在 FXML 中保持其大小