javafx字幕动画

pxiryf3j  于 2021-07-11  发布在  Java
关注(0)|答案(1)|浏览(282)

你可能见过一些应用程序 String 在一个不能完全显示的标签中,它会被设置成动画,并且会前后移动,这样用户就可以看到标签中包含的字符串。当你的手机显示不足以显示整个标签时,android正在做的就是设置。
下面是一个代码来实现它 JavaFX 使用 Service ,但这不是一个好办法。
问题是:下面是如何使用动画或javafx类中的另一个构建来实现它的?
代码:

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;
            }

        };
    }

}
oxf4rvwz

oxf4rvwz1#

你需要一个 Timeline 为此:

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

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

相关问题