JavaFX字幕动画

JavaFX字幕动画,java,animation,javafx,Java,Animation,Javafx,您可能见过一些应用程序,当标签中的字符串无法完全显示时,它会被设置为动画,并前后移动,以便用户可以看到标签中包含的字符串。当您的手机显示不足以显示整个标签时,安卓正在进行设置 下面是使用Service在JavaFX中实现它的代码,但这不是一个好方法 问题是: 下面是我如何使用动画或另一个内置JavaFX类来实现它的 代码: 导入javafx.application.Platform; 导入javafx.concurrent.Service; 导入javafx.concurrent.Task; 导

您可能见过一些应用程序,当标签中的
字符串无法完全显示时,它会被设置为动画,并前后移动,以便用户可以看到标签中包含的字符串。当您的手机显示不足以显示整个标签时,安卓正在进行设置

下面是使用
Service
JavaFX
中实现它的代码,但这不是一个好方法

问题是: 下面是我如何使用动画或另一个内置JavaFX类来实现它的

代码:

导入javafx.application.Platform;
导入javafx.concurrent.Service;
导入javafx.concurrent.Task;
导入javafx.scene.control.Label;
导入javafx.scene.paint.Color;
导入javafx.scene.text.Font;
导入javafx.scene.text.FontWeight;
导入工具.InfoTool;
公共类MoveTitleService扩展服务{
私有字符串标题;
可变布尔分布;
专用int计数器;
public Label movingText=新标签(“真正的YY大T形三通EXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”);
/**
*建造师
*/
公共移动标题服务(){
movingText.setFont(Font.Font(“null”,fontwweight.BOLD,14));
movingText.setTextFill(颜色为白色);
设置成功(s->{
movingText.setText(“”);
});
}
//启动服务
public void startTheService(字符串标题){
this.title=标题;
doAnimation=true;
重启();
}
//停止服务
公共服务{
doAnimation=false;
}
@凌驾
受保护的任务createTask(){
返回新任务(){
@凌驾
受保护的Void调用()引发异常{
while(doAnimation){
//System.out.println(“MoveTitleService正在运行…”);
//一次一封信
对于(int m=0;m{
movingText.setText(title.substring(0,计数器)+addSpaces(title.length()-counter));
});
如果(!doAnimation)中断;
睡眠(150);
}
//向后消失
对于(int m=0;m{
movingText.setText(title.substring(counter));
});
如果(!doAnimation)中断;
睡眠(150);
}
//出现在前面
对于(int m=1;m{
movingText.setText(title.substring(title.length()-counter));
});
如果(!doAnimation)中断;
睡眠(150);
}
如果(!doAnimation)中断;

对于(int i=0;i,您可以使用
时间线来进行此操作:

// min distance to Pane bounds
private static final double OFFSET = 25;

@Override
public void start(Stage primaryStage) {
    Text text = new Text("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    text.setLayoutY(25);
    text.setManaged(false);
    text.setLayoutX(OFFSET);

    Pane pane = new Pane(text);
    pane.setMinHeight(50);

    Timeline timeline = new Timeline();

    KeyFrame updateFrame = new KeyFrame(Duration.seconds(1 / 60d), new EventHandler<ActionEvent>() {

        private boolean rightMovement;

        @Override
        public void handle(ActionEvent event) {
            double tW = text.getLayoutBounds().getWidth();
            double pW = pane.getWidth();
            double layoutX = text.getLayoutX();

            if (2 * OFFSET + tW <= pW && layoutX >= OFFSET) {
                // stop, if the pane is large enough and the position is correct
                text.setLayoutX(OFFSET);
                timeline.stop();
            } else {
                if ((rightMovement && layoutX >= OFFSET) || (!rightMovement && layoutX + tW + OFFSET <= pW)) {
                    // invert movement, if bounds are reached
                    rightMovement = !rightMovement;
                }

                // update position
                if (rightMovement) {
                    layoutX += 1;
                } else {
                    layoutX -= 1;
                }
                text.setLayoutX(layoutX);
            }
        }
    });

    timeline.getKeyFrames().add(updateFrame);
    timeline.setCycleCount(Animation.INDEFINITE);

    // listen to bound changes of the elements to start/stop the animation
    InvalidationListener listener = o -> {
        double textWidth = text.getLayoutBounds().getWidth();
        double paneWidth = pane.getWidth();
        if (textWidth + 2 * OFFSET > paneWidth
                && timeline.getStatus() != Animation.Status.RUNNING) {
            timeline.play();
        }
    };

    text.layoutBoundsProperty().addListener(listener);
    pane.widthProperty().addListener(listener);

    Scene scene = new Scene(pane);

    primaryStage.setScene(scene);
    primaryStage.show();
}
//到窗格边界的最小距离
专用静态最终双偏移=25;
@凌驾
公共无效开始(阶段primaryStage){
文本文本=新文本(“一个真正的YY大Teeeexxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
文本设置布局(25);
text.setManaged(false);
text.setLayoutX(偏移量);
窗格=新窗格(文本);
窗格玻璃设置最小高度(50);
时间线=新时间线();
KeyFrame UpdateName=新的关键帧(持续时间.s(1/60d),新的EventHandler(){
私权运动;
@凌驾
公共无效句柄(ActionEvent事件){
double tW=text.getLayoutBounds().getWidth();
double pW=pane.getWidth();
double layoutX=text.getLayoutX();
如果(2*OFFSET+tW=OFFSET){
//如果窗格足够大且位置正确,则停止
text.setLayoutX(偏移量);
timeline.stop();
}否则{
如果((rightMovement&&layoutX>=偏移量)| |(!rightMovement&&layoutX+tW+OFFSET{
double textWidth=text.getLayoutBounds().getWidth();
双窗格宽度=pane.getWidth();
如果(文本宽度+2*偏移量>窗格宽度
&&timeline.getStatus()!=Animation.Status.RUNNING){
timeline.play();
}
};
text.layoutbundsproperty().addListener(listener);
pane.widthProperty().addListener(listener);
场景=新场景(窗格);
初级阶段。场景(场景);
primaryStage.show();
}

请注意,需要自己重复更新位置,因为运行时无法调整
动画
s,因此,要使任何大小调整在动画期间生效,需要重复更新…

我收到一个错误“关键帧(持续时间,new EventHandler(){}未定义”在第31行..@GoXR3Plus:您是否添加了正确的导入,即导入javafx.animation.KeyFrame;导入javafx.event.ActionEvent;导入javafx.event.EventHandler;导入javafx.util.Duration;
?我在上面的代码中遇到了一些问题:)您能看看问题吗?谢谢您的回答。。。
// min distance to Pane bounds
private static final double OFFSET = 25;

@Override
public void start(Stage primaryStage) {
    Text text = new Text("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    text.setLayoutY(25);
    text.setManaged(false);
    text.setLayoutX(OFFSET);

    Pane pane = new Pane(text);
    pane.setMinHeight(50);

    Timeline timeline = new Timeline();

    KeyFrame updateFrame = new KeyFrame(Duration.seconds(1 / 60d), new EventHandler<ActionEvent>() {

        private boolean rightMovement;

        @Override
        public void handle(ActionEvent event) {
            double tW = text.getLayoutBounds().getWidth();
            double pW = pane.getWidth();
            double layoutX = text.getLayoutX();

            if (2 * OFFSET + tW <= pW && layoutX >= OFFSET) {
                // stop, if the pane is large enough and the position is correct
                text.setLayoutX(OFFSET);
                timeline.stop();
            } else {
                if ((rightMovement && layoutX >= OFFSET) || (!rightMovement && layoutX + tW + OFFSET <= pW)) {
                    // invert movement, if bounds are reached
                    rightMovement = !rightMovement;
                }

                // update position
                if (rightMovement) {
                    layoutX += 1;
                } else {
                    layoutX -= 1;
                }
                text.setLayoutX(layoutX);
            }
        }
    });

    timeline.getKeyFrames().add(updateFrame);
    timeline.setCycleCount(Animation.INDEFINITE);

    // listen to bound changes of the elements to start/stop the animation
    InvalidationListener listener = o -> {
        double textWidth = text.getLayoutBounds().getWidth();
        double paneWidth = pane.getWidth();
        if (textWidth + 2 * OFFSET > paneWidth
                && timeline.getStatus() != Animation.Status.RUNNING) {
            timeline.play();
        }
    };

    text.layoutBoundsProperty().addListener(listener);
    pane.widthProperty().addListener(listener);

    Scene scene = new Scene(pane);

    primaryStage.setScene(scene);
    primaryStage.show();
}