I wrote my first animation in Java FX and would like a code review.
I created StackPane
with Rectangle
. Rectangle
starts to move inside StackPane
to right-bottom direction and changes direction after hitting the StackPane
bound.
Please review the code that moves Rectangle
. Is it a correct implementation of a Java FX animation?
//...
new RectangleMover(pane, shape);
// ...
RectangleMover.java
public class RectangleMover extends Timer
{
private final StackPane pane;
private final Rectangle shape;
private boolean moveRight = true;
private boolean moveBottom = true;
public RectangleMover(StackPane pane, Rectangle shape)
{
super(true);
this.pane = pane;
this.shape = shape;
this.scheduleAtFixedRate(new Task(), 0, 10);
}
private static int boolToInt(boolean bool)
{
return bool ? 1 : -1;
}
private final class Task extends TimerTask
{
@Override
public void run()
{
shape.setLayoutX(shape.getLayoutX() + boolToInt(moveRight));
shape.setLayoutY(shape.getLayoutY() + boolToInt(moveBottom));
if (shape.getLayoutX() >= pane.getWidth() - shape.getWidth())
{
moveRight = false;
}
if (shape.getLayoutY() >= pane.getHeight() - shape.getHeight())
{
moveBottom = false;
}
if (shape.getLayoutX() <= 0)
{
moveRight = true;
}
if (shape.getLayoutY() <= 0)
{
moveBottom = true;
}
}
}
}
JFXTester.java (main class)
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;
public class JFXTester extends Application
{
StackPane root;
@Override
public void start(Stage primaryStage)
{
root = new StackPane();
root.getChildren().add(createStartButton());
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
private Rectangle createRectangle()
{
Rectangle r = new Rectangle();
r.setX(0);
r.setY(0);
r.setWidth(30);
r.setHeight(30);
r.setFill(new Color(0.8, 0.7, 0.6, 0.5));
return r;
}
private Button createStartButton()
{
final Button btn = new Button();
btn.setText("START!");
btn.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
btn.setVisible(false);
Rectangle r = createRectangle();
root.getChildren().add(r);
new RectangleMover(root, r);
}
});
return btn;
}
public static void main(String[] args)
{
launch(args);
}
}
How to run application (java 1.7.0_51-b13):
D:\.temporary\java>dir /a-d /b /s
D:\.temporary\java\jfxtester\JFXTester.java
D:\.temporary\java\jfxtester\RectangleMover.java
D:\.temporary\java>%JAVA_HOME%\bin\javac -cp .;%JRE_HOME_7%\lib\jfxrt.jar ./jfxtester/JFXTester.java
D:\.temporary\java>%JRE_HOME_7%\bin\java -cp .;%JRE_HOME_7%\lib\jfxrt.jar jfxtester.JFXTester
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
. I would recommend posting this on StackOverflow, with this specific error message. \$\endgroup\$Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
). You ask "Is it a correct implementation of a Java FX animation?" and I don't think this is working as expected as you say. I would love to help you clean up some things in the code, but it is better if you fix the problem first. If you search for "Not on FX application thread" you should find a solution. Please come back and update your code here once you have fixed that problem. \$\endgroup\$