我写了一个javafx应用程序。
我想每10毫秒更新一次标签宽度,其中标签代表一个值。
一般来说,我成功地做到了这一点,但有一个问题:标签闪烁的小值,在相反的大值。
在我以前的作品中,我注意到progressbar控件具有平滑的大小调整动画。
所以,我想让它像progressbar一样工作(平滑)。
下面是解释问题的示例代码:
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class MainApplication extends Application {
private static final String LABEL_STYLE = "-fx-font-weight: bold; -fx-border-style: solid; -fx-pref-height: 38; -fx-background-color: ";
private static final double MAX_WIDTH = 760;
private static final double MAX_VALUE = 60000;
private static final double VALUE_PER_PIXEL_RATIO = MAX_VALUE / MAX_WIDTH;
private static final int ANIMATION_DURATION = 9000;
private static final int KEYFRAME_DURATION = 10;
private static final int ANIMATION_CYCLES = ANIMATION_DURATION / KEYFRAME_DURATION;
private final Label label_1 = new Label();
private final Label label_2 = new Label();
private final Label label_3 = new Label();
@Override
public void start(Stage primaryStage) {
label_1.setStyle(LABEL_STYLE + " #4363d8; ");
label_2.setStyle(LABEL_STYLE + " #ffe119; ");
label_3.setStyle(LABEL_STYLE + " #3cb44b; ");
VBox root = new VBox();
root.setSpacing(10);
root.setPadding(new Insets(40, 30, 30, 30));
root.getChildren().addAll(label_1, label_2, label_3);
root.getChildren().addAll(new Label("Label 1 : Good (Smooth)"),
new Label("Label 2 : Acceptable"),
new Label("Label 3 : Weak (Blinks)"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setWidth(800);
primaryStage.setHeight(350);
primaryStage.show();
playAnimation();
}
private void playAnimation() {
MyData myData_1 = new MyData(58000, ANIMATION_CYCLES, VALUE_PER_PIXEL_RATIO);
MyData myData_2 = new MyData(20000, ANIMATION_CYCLES, VALUE_PER_PIXEL_RATIO);
MyData myData_3 = new MyData(4000, ANIMATION_CYCLES, VALUE_PER_PIXEL_RATIO);
final Timeline timeline = new Timeline();
timeline.setCycleCount(ANIMATION_CYCLES);
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(KEYFRAME_DURATION), new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent actionEvent) {
label_1.setPrefWidth(myData_1.getCurrentWidth());
label_2.setPrefWidth(myData_2.getCurrentWidth());
label_3.setPrefWidth(myData_3.getCurrentWidth());
}
}));
timeline.play();
// Replay animation
timeline.setOnFinished(event -> playAnimation());
}
public static void main(String[] args) {
launch(args);
}
}
class MyData {
private double currentValue;
private double currentWidth;
private double incrementStep;
private static double VALUE_PER_PIXEL_RATIO;
public MyData(int maxValue, double cycles, double ratio) {
super();
this.incrementStep = maxValue / cycles;
VALUE_PER_PIXEL_RATIO = ratio;
}
public double getCurrentWidth() {
currentWidth = currentValue / VALUE_PER_PIXEL_RATIO;
currentValue += incrementStep;
return currentWidth;
}
}
谢谢。
1条答案
按热度按时间nkhmeac61#
对我来说,它不会闪烁,在DebianLinux上使用JavaFX15,使用intel集成图形芯片。
你正在做大量的工作,以动画的标签自己。与其自己制作动画,不如让时间轴来进行插值:
我不确定强制每秒100帧是否有用。javafx似乎非常擅长在不指定帧速率的情况下创建平滑动画: