【问题标题】:Make JavaFX wait and continue with code让 JavaFX 等待并继续执行代码
【发布时间】:2014-12-14 18:09:28
【问题描述】:

基本上,我正在尝试使用 JavaFX 做一个简短的效果。我有一个心的形状(由两个圆圈和一个多边形相加),我可以使用双精度值p 来改变它的大小。 “标准尺寸”为p = 1.0;

我正在尝试为心脏添加泵送效果。我有pumpOnce()的方法:

public void pumpOnce(){
    p = p + 1;
    initHeart();
    //Here goes what ever it takes to make stuff working!!
    p = p - 1;
    initHeart();
}

initHeart()根据p画心。

我发现 Thread.sleep(); 或类似方法由于 JavaFX 中的线程哲学而无法工作。

但是我可以用什么代替呢?

【问题讨论】:

  • 您可以使用PauseTransitionTimelineKeyFrames 来构建更复杂/自定义的动画过渡。
  • 是的,我确实在 Uluk 附近的某个地方看到了你的答案,但我并没有真正尝试进行过渡,但基本上是两帧动画。我可以使用类似于Thread.sleep()Timeline 吗?
  • A PauseTransition 不必与节点关联。您可以只创建一个,使用它的setOnFinished 处理程序让代码在暂停后执行,然后调用play() 来启动它。

标签: javafx wait thread-sleep


【解决方案1】:

JavaFX 动画可能是要走的路,但如果您想自己滚动或在后台线程中做其他更复杂的事情,JavaFX 中的“线程哲学”并不难使用。

以下代码将暂停并更改标签中的值(完全公开,我正在重用我为另一个问题编写的代码):

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloWorld extends Application {

    private static Label label;

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

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        label = new Label();
        label.setText("Waiting...");
        StackPane root = new StackPane();
        root.getChildren().add(label);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();

        Task<Void> sleeper = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
                return null;
            }
        };
        sleeper.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent event) {
                label.setText("Hello World");
            }
        });
        new Thread(sleeper).start();
    }
}

基本的 JavaFX 后台工具是 Task,任何实际执行任何操作的 JavaFX 应用程序都可能到处都是这些。了解如何使用它们。

【讨论】:

  • 谢谢,正是我需要的!
【解决方案2】:

Dave 的解决方案非常适合 JavaFX 中基于线程的通用工作。

如果您希望使用 JavaFX 的动画功能,下面的解决方案将使用 Timeline 或 ScaleTransition 进行演示。时间线实现了 UI 元素的离散比例,因此每四分之一秒 UI 元素都会放大或恢复到其原始大小。缩放过渡实现了 UI 元素的平滑缩放,因此 UI 元素使用带有default easing interpolator 的插值缩放因子逐渐变大然后变小。

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class BeatingHeart extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage stage) {
        ImageView heart = new ImageView(HEART_IMAGE_LOC);

        animateUsingTimeline(heart);
//        animateUsingScaleTransition(heart);

        StackPane layout = new StackPane(heart);
        layout.setPrefWidth(heart.getImage().getWidth() * 2);
        layout.setPrefHeight(heart.getImage().getHeight() * 2);

        Scene scene = new Scene(layout);
        stage.setScene(scene);
        stage.show();
    }

    private void animateUsingTimeline(ImageView heart) {
        DoubleProperty scale = new SimpleDoubleProperty(1);
        heart.scaleXProperty().bind(scale);
        heart.scaleYProperty().bind(scale);

        Timeline beat = new Timeline(
            new KeyFrame(Duration.ZERO,         event -> scale.setValue(1)),
            new KeyFrame(Duration.seconds(0.5), event -> scale.setValue(1.1))
        );
        beat.setAutoReverse(true);
        beat.setCycleCount(Timeline.INDEFINITE);
        beat.play();
    }

    private void animateUsingScaleTransition(ImageView heart) {
        ScaleTransition scaleTransition = new ScaleTransition(
            Duration.seconds(1), heart
        );
        scaleTransition.setFromX(1);
        scaleTransition.setFromY(1);
        scaleTransition.setFromZ(1);
        scaleTransition.setToX(1.1);
        scaleTransition.setToY(1.1);
        scaleTransition.setToZ(1.1);
        scaleTransition.setAutoReverse(true);
        scaleTransition.setCycleCount(Animation.INDEFINITE);
        scaleTransition.play();
    }

    private static final String HEART_IMAGE_LOC =
            "http://icons.iconarchive.com/icons/mirella-gabriele/valentine/128/Heart-red-icon.png";
    // icon obtained from: http://www.iconarchive.com/show/valentine-icons-by-mirella-gabriele/Heart-red-icon.html
    // icon license: Free for non-commercial use, commercial use not allowed.
}

【讨论】:

    猜你喜欢
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 2019-02-02
    • 2018-05-19
    相关资源
    最近更新 更多