JavaFX Marquee动画 [英] JavaFX Marquee Animation

查看:152
本文介绍了JavaFX Marquee动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您可能已经看过一些应用程序,当标签中的 String 无法完全显示时,它会被设置为动画并且会返回和返回,以便用户可以看到选项卡包含的字符串。当您的手机显示不足以显示整个标签时,Android正在进行设置。

You maybe have seen some apps that when the String in a tab can't be fully shown then it is animated and is going back and front so the user can see what String the tab contains.Android is doing that is settings when your phone display is not enough to show the the whole label.

以下是在 JavaFX 使用服务,但这不是一个好方法。

Below is a code to achieve it in JavaFX using Service,but it is not a good way.

问题是:
以下是我如何使用动画或JavaFX类中的其他构建来实现的?

The Question is: Here is how i can do it using Animation or another build in JavaFX class?

代码:

import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import tools.InfoTool;

public class MoveTitleService extends Service<Void>{
    private String title;
    volatile boolean doAnimation;
    private int counter;
    public Label movingText = new Label("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt");


    /**
     *Constructor
    */
    public MoveTitleService() {
         movingText.setFont(Font.font("null",FontWeight.BOLD,14));
         movingText.setTextFill(Color.WHITE);   

         setOnSucceeded( s ->{
             movingText.setText("");
         });
    }

    //Start the Service
    public void startTheService(String title) {
        this.title = title;
        doAnimation = true;

        restart();
    }


    //Stop the Service
    public void stopService(){
        doAnimation=false;
    }

    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            @Override
            protected Void call() throws Exception {

                while (doAnimation) {
                    //System.out.println("MoveTitleService is Running...");

                    // One letter at a time
                    for (int m = 0; m <= title.length(); m++) {
                        counter=m;

                        Platform.runLater( () ->{
                            movingText.setText(title.substring(0, counter) + addSpaces(title.length() - counter));      
                        });

                        if(!doAnimation) break;
                        Thread.sleep(150);
                    }

                    // Disappearing to back
                    for (int m = 0; m < title.length(); m++) {
                        counter=m;

                        Platform.runLater( () ->{
                            movingText.setText(title.substring(counter));
                        });

                        if(!doAnimation) break;
                        Thread.sleep(150);
                    }

                    // Appearing to front
                    for (int m = 1; m <= title.length(); m++) {
                        counter=m;

                        Platform.runLater( () ->{
                            movingText.setText(title.substring(title.length() - counter));
                        });

                        if(!doAnimation) break;
                        Thread.sleep(150);
                    }

                    if(!doAnimation) break;
                    for(int i=0; i<3000/150; i++)
                        Thread.sleep(150);
                    Thread.sleep(3000);

                }

                return null;
            }

            private String addSpaces(int spaces) {
                String z = "";
                for (int i = 0; i <= spaces; i++)
                    z += " ";

                return z;
            }

        };
    }

}


推荐答案

您可以使用时间轴

// 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();
}

请注意,需要自行重复更新头寸,因为<$ c运行时无法调整$ c>动画,因此在动画期间任何调整大小都需要重复更新...

Note that repeadedly updating the position yourself needs to be done, since Animations cannot be adjusted while running, so for any resizing to take effect during the animation, you need repeated updates...

这篇关于JavaFX Marquee动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆