我目前正在使用 JavaFX 开发一个带有动画的应用程序。该应用程序由人工校正员使用,校正计算机生成的字幕。动画中有一个 float 文本。我的问题是动画有时会关闭。您可以看下面的图片进行演示:
此缺陷主要发生在调整大小之后。当动画中断时,它永远不会再次达到完全运行的状态。 我使用插入 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/