2014-10-19 735 views
5

基本上我试图用JavaFX做一个短暂的效果。我有一个心脏的形状(由两个圆圈和一个多边形加在一起),我可以使用双倍值p来改变大小。 “标准尺寸”将是p = 1.0;让JavaFX等待并继续执行代码

我想增加抽水效果的心脏。我有方法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中的线程原理而不起作用。

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

+0

您可以使用'PauseTransition'或'Timeline'和'KeyFrame'来构建更复杂/自定义的动画过渡。 – 2014-10-19 19:00:25

+0

是的,我确实在乌鲁克附近的某个地方看到了你的答案,但我并不是真的想要做一个过渡,但基本上是一个两帧动画。我可以使用'Timeline'类似于'Thread.sleep()'吗? – Maverick283 2014-10-19 19:04:50

+1

'PauseTransition'不必与节点关联。你可以创建一个,使用它的'setOnFinished'处理程序让代码在暂停后执行,并调用'play()'来启动它。 – 2014-10-19 19:43:02

回答

10

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的背景工具是任务,任何的JavaFX实际上做任何事情的应用程序可能都会随着这些而散布。了解如何使用它们。

3

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

如果您希望使用JavaFX的动画设施,下面的解决方案使用时间轴或ScaleTransition演示了这一点。时间轴实现了UI元素的离散缩放比例,因此UI元素的每一秒都会缩放或恢复到原始大小。缩放转换实现了UI元素的平滑缩放,因此使用default easing interpolator的插值缩放因子,UI元素逐渐变大然后变小。

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