我有两个圈子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();
答案 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));
这里增加的好处是你创建一个布尔值来表示灯是否亮起,这可能在你的逻辑中的其他地方有用,并且你将逻辑(开/关和时间)与显示分开(颜色等)。