I have an Java FX scene with a start button and several rectangles which represent the tiles of a map. I also have drawn a sphere which represents my explorer (it has to exp
This is because of :
exception : Test cannot be cast to javafx.event.EventHandler
Well, I have no idea how Class cast exception came up.
Otherwise, to delay, you can use Thread.sleep()
.
UPDATE:
Its good to use AnimationTimer to create an animation, you don't need to refresh anything.
Here, I have done a short EG to show color rect using FillTransition
.
CODE:
import javafx.animation.FillTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class NewFXMain1 extends Application {
private static final double boxOuterSize = 50;
private static final double boxInnerSize = 48;
private static final double boxCornerRadius = 20;
private Rectangle rectangles = new Rectangle();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("rect");
Button btn = new Button();
StackPane root = new StackPane();
Rectangle r = new Rectangle();
r.setFill(Color.BLUE);
r.setX(2 * boxOuterSize);
r.setY(0);
r.setWidth(boxInnerSize);
r.setHeight(boxInnerSize);
r.setArcHeight(boxCornerRadius);
r.setArcWidth(boxCornerRadius);
r.setSmooth(true);
r.localToScene(boxOuterSize, boxOuterSize);
rectangles = r;
root.getChildren().add(rectangles);
btn.setText("display");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
FillTransition ft = new FillTransition(Duration.millis(3000), rectangles, Color.RED, Color.BLUE);
ft.setCycleCount(4);
ft.setAutoReverse(true);
ft.play();
}
});
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
This is an old question and it caught my eye since this is a very general issue faced by people new to JavaFX.
The problem that OP is facing is because he updates all the rectangles at once, without waiting.
OP can wait by either creating a new Thread, put the thread on sleep for an estimated seconds for every iteration of the loop and then update the color of the rectangle on JavaFX application thread by using Platform.runLater
.
@Override
public void handle(Event arg0) {
new Thread(() -> {
for(int i=0; i<10; i++) {
try {
Thread.sleep(1000); // Wait for 1 sec before updating the color
} catch (InterruptedException e) {
e.printStackTrace();
}
int finalI = i;
Platform.runLater(() -> rectangles[finalI].setFill(Color.RED));// Update on JavaFX Application Thread
}
}).start();
The above snippet is more of a traditional way of doing things. If we want to use the "JavaFX" ways of doing things, we can achieve the same by using an Animation
.
Below is a code snippet which will wait for x-seconds
before changing the color of the rectangle. It doesn't need any extra thread since the wait is handled by PauseTransition
applied for each rectangle.
startButton.setOnMouseClicked(new EventHandler<Event>() {
@Override
public void handle(Event arg0) {
for(int i=0; i<10; i++) {
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(i));
int finalI = i;
pauseTransition.setOnFinished(event -> rectangles[finalI].setFill(Color.RED));
pauseTransition.play();
}
}
});
It creates a PauseTransition for each rectangle and depending on its index in the array rectangles
, it waits for the same number of seconds before updating the color.