JavaFX MultiThreading闪烁灯

时间:2015-08-06 22:27:12

标签: javafx

我有两个圈子redCircle和greenCircle: -

Circle greenCircle = new Circle(250,150 ,100, Color.TRANSPARENT);
Circle redCircle = new Circle(250,450,100,Color.TRANSPARENT);        
greenCircle.setStroke(Color.GREEN);
greenCircle.setStrokeWidth(4);
group.getChildren().add(greenCircle); 
redCircle.setStroke(Color.RED);
redCircle.setStrokeWidth(4);
group.getChildren().add(redCircle);  

基本上我希望Circle在2秒内打开和关闭两次。所以我可以打开Light然后等待0.5秒,关闭再等待0.5秒并打开Light。我不打算在0.5秒后关闭。

 public class LightOn {
                    public Task<Void> runLightOn() throws InterruptedException {
                         return new Task<Void>(){
                             @Override
                             protected Void call() throws Exception { 
                                 greenCircle.setFill(Color.GREEN);                              
                                 return null;
                             }                            
                         };
                    }                   
                }
                public class LightOff {
                    public void perform() throws InterruptedException {
                        LightOn onL = new LightOn();
                        Task<Void> runLinghtOnTask = onL.runLightOn();
                        runLinghtOnTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                            @Override
                            public void handle(WorkerStateEvent event) {                              
                               try {                                     
                                   Thread.sleep(500);
                                } catch (InterruptedException ex) {
                                   Logger.getLogger(MovementEventsDemo.class.getName()).log(Level.SEVERE, null, ex);
                                }
                                 greenCircle.setFill(Color.TRANSPARENT);                               
                               nextFunction();
                            }
                        });
                        new Thread(runLinghtOnTask).start();
                    }                     
                }
                public void nextFunction(){
                            Task<Void> sleeper2 = new Task<Void>() {
                            @Override
                            protected Void call() throws Exception {

                                try {                                               
                                            Thread.sleep(500);      

                                } catch (InterruptedException e) {
                                }
                                return null;
                            }
                        };                 
                        sleeper2.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                         @Override
                         public void handle(WorkerStateEvent event) {
                             if(greenCircle.getFill()==Color.GREEN) {
                                 greenCircle.setFill(Color.TRANSPARENT); 
                             }else {
                                  greenCircle.setFill(Color.GREEN);                 
                             }                        
                        }
                     });                
                        new Thread(sleeper2).start();
                }     

我用它来执行: -

 LightOff lf = new LightOff();
  lf.perform();

1 个答案:

答案 0 :(得分:2)

您的代码无效的原因是call()返回的Task runLightOn()方法引发了异常,因为您正在从后台线程更改UI 。如果您捕获异常或使用onFailed注册Task处理程序,您将能够记录异常。

对于这样的功能,如果你有值要更改值的特定时间点(KeyFrame s),请使用Timeline而不是搞乱多线程:

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;


public class FlashingLight extends Application {

    @Override
    public void start(Stage primaryStage) {
        Circle circle = new Circle(250, 150, 100, Color.TRANSPARENT);
        circle.setStroke(Color.GREEN);
        circle.setStrokeWidth(4);

        Timeline timeline = new Timeline(
                new KeyFrame(Duration.seconds(0.5), e -> circle.setFill(Color.GREEN)),
                new KeyFrame(Duration.seconds(1.0), e -> circle.setFill(Color.TRANSPARENT))
        );

        timeline.setCycleCount(2);

        Pane pane = new Pane(circle);

        Scene scene = new Scene(pane, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();

        timeline.play();
    }

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

作为一种替代方案,您可以替换

    Timeline timeline = new Timeline(
            new KeyFrame(Duration.seconds(0.5), e -> circle.setFill(Color.GREEN)),
            new KeyFrame(Duration.seconds(1.0), e -> circle.setFill(Color.TRANSPARENT))
    );

    BooleanProperty on = new SimpleBooleanProperty();
    Timeline timeline = new Timeline(
            new KeyFrame(Duration.seconds(0.5), new KeyValue(on, true)),
            new KeyFrame(Duration.seconds(1.0), new KeyValue(on, false))
    );
    circle.fillProperty().bind(
        Bindings.when(on)
                .then(Color.GREEN)
                .otherwise(Color.TRANSPARENT));

这里增加的好处是你创建一个布尔值来表示灯是否亮起,这可能在你的逻辑中的其他地方有用,并且你将逻辑(开/关和时间)与显示分开(颜色等)。