使用 JavaFX 的脉动不透明效果

Pulsating opacity effect with JavaFX

我对我的申请有一个简单的要求,但我不确定哪个是最好的解决方案。

假设我有 10 个按钮,我只想要一个不透明度为 1.0 的按钮。它们旁边的按钮应该有 0.6,下一个按钮应该有 0.4。所有其他的都有 0.2.

现在我想要一个制作脉动动画的时间轴。不透明度为 1.0 的按钮应变为 0.2,直到上一个按钮开始提高不透明度并达到 0.4 的值。

我现在无法更好地描述它,但我想大多数人都知道它的效果。

第一次尝试

创建 10 个时间线并在完成另一个时间线时开始每个时间线 - 但我希望有一个只有一个时间线的解决方案

第二次尝试

一个时间轴,其中每个关键帧在开始之前都有延迟 - 但我发现整个动画只有延迟。

这是一个最小的例子,但我认为这并没有什么帮助,因为这只是基础。

  package com.example.demo;

  import javafx.application.Application;
  import javafx.scene.Scene;
  import javafx.scene.control.Button;
  import javafx.scene.layout.VBox;
  import javafx.stage.Stage;

  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;

  public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {

    List<Button> allButtons = new ArrayList<>();
    VBox vBox = new VBox(20);

    for (int i = 0; i < 10; i++) {
        Button button = new Button("Test");
        button.setOpacity(0.2);
        allButtons.add(button);
        vBox.getChildren().add(button);
    }

    allButtons.get(1).setOpacity(0.4);
    allButtons.get(2).setOpacity(0.6);
    allButtons.get(3).setOpacity(1.0);
    allButtons.get(4).setOpacity(0.6);
    allButtons.get(5).setOpacity(0.4);

    Scene scene = new Scene(vBox, 1200, 800);
    stage.setScene(scene);
    stage.show();
}


  }

迭代期间的示例不透明度值

Iteration Button A Button B Button C Button D Button E Button F Button G Button H
1 0.2 0.2 0.4 0.6 1.0 0.6 0.4 0.2
2 0.2 0.2 0.2 0.4 0.6 1.0 0.6 0.4
3 0.4 0.2 0.2 0.2 0.4 0.6 1.0 0.6
4 0.6 0.4 0.2 0.2 0.2 0.4 0.6 1.0
5 1.0 0.6 0.4 0.2 0.2 0.2 0.4 0.6
6 0.6 1.0 0.6 0.4 0.2 0.2 0.2 0.4
7 0.4 0.6 1.0 0.6 0.4 0.2 0.2 0.2
8 0.2 0.4 0.6 1.0 0.6 0.4 0.2 0.2

然后从迭代 1 重新开始。还应该使用这些不透明度值之间的过渡,以便它是那些不透明度值之间的平滑过渡。

许多问候, 豪克

尝试链接 FadeTransition

     FadeTransition ft = new FadeTransition(Duration.millis(3000), allButtons.get(3));
     ft.setFromValue(1.0);
     ft.setToValue(0.2);
     ft.play();

     ft.setOnFinished( (e)-> { /* next Fade Transition */  } );

此代码使用 TimelineFadeTransitionParallelTransition 每秒更改按钮的不透明度。

import java.util.ArrayList;
import java.util.List;
import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.animation.KeyFrame;
import javafx.animation.ParallelTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class App extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    
    
    @Override
    public void start(Stage primaryStage) {
        VBox vBox = new VBox();
        vBox.setSpacing(2);

        List<String> buttonTextList = new ArrayList();
        buttonTextList.add("A");
        buttonTextList.add("B");
        buttonTextList.add("C");
        buttonTextList.add("D");
        buttonTextList.add("E");
        buttonTextList.add("F");
        buttonTextList.add("G");
        buttonTextList.add("H");
                
        FadeTransition ftStepOne = new FadeTransition(Duration.seconds(.9));
        ftStepOne.setToValue(0.2);
        FadeTransition ftStepTwo = new FadeTransition(Duration.seconds(.9));
        ftStepTwo.setToValue(0.2);
        FadeTransition ftStepThree = new FadeTransition(Duration.seconds(.9));
        ftStepThree.setToValue(0.4);
        FadeTransition ftStepFour = new FadeTransition(Duration.seconds(.9));
        ftStepFour.setToValue(0.6);
        FadeTransition ftStepFive = new FadeTransition(Duration.seconds(.9));
        ftStepFive.setToValue(1.0);
        FadeTransition ftStepSix = new FadeTransition(Duration.seconds(.9));
        ftStepSix.setToValue(0.6);
        FadeTransition ftStepSeven = new FadeTransition(Duration.seconds(.9));
        ftStepSeven.setToValue(0.4);
        FadeTransition ftStepEight = new FadeTransition(Duration.seconds(.9));
        ftStepEight.setToValue(0.2);
        List<FadeTransition> buttonStateList = new ArrayList();
        buttonStateList.add(ftStepOne);
        buttonStateList.add(ftStepTwo);
        buttonStateList.add(ftStepThree);
        buttonStateList.add(ftStepFour);
        buttonStateList.add(ftStepFive);
        buttonStateList.add(ftStepSix);
        buttonStateList.add(ftStepSeven);
        buttonStateList.add(ftStepEight);
        
        List<Button> allButtons = new ArrayList<>();
        for (int i = 0; i < buttonTextList.size(); i++) {
            Button button = new Button(buttonTextList.get(i));
            button.setPrefWidth(100);
            button.setStyle("-fx-background-color: blue;");
            allButtons.add(button);
            vBox.getChildren().add(button);
        }
        
        final ParallelTransition parallelTransition = new ParallelTransition (); 
        parallelTransition.getChildren().addAll(buttonStateList);
                
        final Timeline timeleine = new Timeline(
            new KeyFrame(Duration.seconds(1), (ActionEvent event) -> {
                
                for(int i = 0; i < allButtons.size(); i++)
                {
                    System.out.println(allButtons.get(i).getText() + "\tFrom: " + allButtons.get(i).getOpacity() + "\tTo: " + buttonStateList.get(i).getToValue());
                    buttonStateList.get(i).setNode(allButtons.get(i));                                   
                }
                               
                parallelTransition.play();
                
                FadeTransition addFtToEnd = buttonStateList.get(0);
                buttonStateList.remove(addFtToEnd);
                buttonStateList.add(addFtToEnd);
        }));
        timeleine.setCycleCount(Timeline.INDEFINITE);

        Button startBtn = new Button("Start");
        startBtn.setOnAction(event ->{
            if(timeleine.getStatus() == Animation.Status.STOPPED || timeleine.getStatus() == Animation.Status.PAUSED)
            {
                timeleine.play();
                startBtn.setText("Stop");
                System.out.println(timeleine.getStatus());
            }
            else if(timeleine.getStatus() == Animation.Status.RUNNING)
            {
                timeleine.pause();
                startBtn.setText("Start");
            }
        });
        vBox.getChildren().add(startBtn);
        
        Scene scene = new Scene(vBox, 1200, 800);

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

    }
}