JAVA FX - TimeLine Animation (Find certain x,y point during animation) - java

In this program, I am trying to make rect turn red when x== 600 in the for-loop. What basically happens is that the for-loop runs faster than the animation on the screen. The rectangle ends up turning red before it actually hits that certain point within the JavaFX screen.
What I would like it to do it that when it hits point x,y:(600,500), make the blue rectangle turn red.
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
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.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* #author Owner
*/
public class TestPoint extends Application {
#Override
public void start(Stage primaryStage) {
Pane root = new Pane();
Scene scene = new Scene(root, 1000, 1000);
Rectangle rect = new Rectangle();
Rectangle rectTwo = new Rectangle();
//Obstacle that other square must hit
rectTwo.setWidth(100);
rectTwo.setHeight(100);
rectTwo.setX(500);
rectTwo.setY(500);
rectTwo.setFill(Color.PINK);
//for loop that causes the animation to properly move
for (int x = 800; x >= 0; x--) {
rect.setWidth(100);
rect.setHeight(100);
rect.setX(800);
rect.setY(500);
rect.setFill(Color.BLUE);
Timeline timeline = new Timeline();
timeline.setCycleCount(1);
timeline.setAutoReverse(true);
final KeyValue kv = new KeyValue(rect.xProperty(), x);
final KeyFrame kf = new KeyFrame(Duration.seconds(8), kv);
timeline.getKeyFrames().add(kf);
timeline.play();
//if it hits the point of rectTwo, change to Color.RED
System.out.println(x);
if (x == 600) {
rect.setFill(Color.RED);
break;//end
}
}
root.getChildren().addAll(rect, rectTwo);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

You misunderstood, how Timeline works. Your code creates 201 Timeline animations running in parallel. The loop is done before the window is shown. Any updates are automatically triggered by JavaFX later.
Specifying the initial state and the target state via KeyFrames is sufficient. KeyFrames allow you to specify a handler to be executed at a specific time; this can be used to change the color. Alternatively the onFinished handler could be used for coloring the Rectangle.
rect.setWidth(100);
rect.setHeight(100);
rect.setY(500);
rect.setFill(Color.BLUE);
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(rect.xProperty(), 800)),
new KeyFrame(Duration.seconds(8),
evt -> rect.setFill(Color.RED),
new KeyValue(rect.xProperty(), 600)));
timeline.play();

Related

How should I proceed in making my player rectangle jump?

I'm just looking to make my red rectangle jump up when you press that jump button. I can't really seem to find any thing like an animation or even a go up, wait a certain amount of time and then come back down.
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
import javafx.animation.PathTransition;
import javafx.scene.shape.*;
import javafx.util.Duration;
public class GUIPractice extends Application{
public static void main (String [] args)
{
launch(args);
}
public void start (Stage primaryStage)
{
Rectangle screen = new Rectangle(20, 20, 986, 500);
Button JumpBtn = new Button("Jump");
JumpBtn.setLayoutX(410);
JumpBtn.setLayoutY(530);
JumpBtn.setMinWidth(200);
JumpBtn.setMinHeight(100);
Rectangle player = new Rectangle(450, 420, 50, 100);
player.setFill(Color.RED);
Path path = new Path();
I believe right here below is where the jumping would go but the only thing I could figure out is how to get the rectangle to move up on the screen and not move back down.
JumpBtn.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(ActionEvent e) {
player.setTranslateY(-40);
}
});
Group root = new Group(screen, JumpBtn, player);
Scene scene = new Scene(root, 1024, 768);
scene.setFill(Color.GREY);
primaryStage.setTitle("GUIPractice");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Use a animation such as timeline to move the Node, e.g.
double ty = player.getTranslateY();
// quadratic interpolation to simulate gravity
Interpolator interpolator = new Interpolator() {
#Override
protected double curve​(double t) {
return t * (2 - t);
}
};
Timeline timeline = new Timeline(new KeyFrame(Duration.ZERO,
new KeyValue(player.translateYProperty(), ty, interpolator)),
new KeyFrame(Duration.seconds(1),
new KeyValue(player.translateYProperty(), ty-40, interpolator)));
// play forward once, then play backward once
timeline.setCycleCount(2);
timeline.setAutoReverse(true);
JumpBtn.setDisable(true);
timeline.setOnFinished(evt -> JumpBtn.setDisable(false));
timeline.play();

JavaFX Using TimeLine to Pause Program

I need to set my background colour of my Pane for one second and then switch it to transparent. I have this set up to change the background colour, use a TimeLine with a duration of 1000ms to pause it, and then switch to transparent.
The Timeline is not pausing and the program is flying past it and setting the background to transparent too quickly. Anyone know how to fix this?
I can not use thread.sleep or anything like that because of the scope of this project.
package assign3;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Question2 extends Application
{
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLUE = 3;
public static final int ORANGE = 4;
#Override
public void start( Stage obPrimeStage ) throws Exception
{
boolean runGame = true;
int level = 1;
BorderPane obBorder = new BorderPane();
HBox obPane = new HBox();
HBox obStart = new HBox();
Button btRed = new Button("Red");
Button btGreen = new Button("Green");
Button btBlue = new Button("Blue");
Button btOrange = new Button("Orange");
Button btStart = new Button("Start");
Timeline pause = new Timeline();
pause.setCycleCount(1);
pause.getKeyFrames().add(new KeyFrame(Duration.millis(1000)));
obStart.getChildren().add(btStart);
obPane.getChildren().addAll(btRed, btGreen, btBlue, btOrange);
obBorder.setCenter(obPane);
obBorder.setBottom(obStart);
obPane.setAlignment(Pos.CENTER);
obStart.setAlignment(Pos.CENTER);
Scene obScene = new Scene(obBorder, 400, 400);
obPrimeStage.setTitle("Question 2");
obPrimeStage.setScene(obScene);
obPrimeStage.show();
ArrayList<Integer> colours = new ArrayList<>();
ArrayList<Integer> guesses = new ArrayList<>();
btStart.setOnAction((ActionEvent start) -> {
for(int i = 0; i <= level; i++)
{
int randomColour = (int)((Math.random() * 4) + 1);
randomColour = 1;
if(randomColour == RED)
{
obBorder.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
pause.play();
obBorder.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)));
colours.add(RED);
}
You are using Timeline as a substitute for Thread.sleep. That is not how Timeline works.
When you call play() on an Animation, it starts the animation in the background and returns immediately.
Have a look at the constructors of the KeyFrame class. You need to pass a KeyValue to your KeyFrame, so a change occurs at the point in time represented by the KeyFrame:
pause.getKeyFrames().add(new KeyFrame(Duration.ZERO,
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)))));
pause.getKeyFrames().add(new KeyFrame(Duration.millis(1000),
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)))));
As you can see, a KeyValue consists of two parts: a property, and the new value you want assigned to that property at some point during the animation.
The first at Duration.ZERO (the start), which sets the background property to your starting color.
The second occurs after 1000 milliseconds have passed, and sets the background property to transparent again.
By the way, you might find Duration.seconds(1) a little more readable.

JavaFX rectangle rotation pivot from point other than top left

I have applied a JavaFx Rotation to a rectangle using the constructor that allows you to set the pivot
new Rotate(45, 15, 15)
This rotates the rectangle but it rotates around the top left corner at 15,15 on the AnchorPane in which it is placed. Is it possible to rotate a rectangle around a point that acts like the center of a circle and the rectangle rotates around the circumfrence. Like the rectangle is a piece of tread on a tire that rotates around the central pivot. Thanks heaps.
This works for me, I am not sure what you are doing though.
package helloworld;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import java.time.Duration;
/**
* Created by Matt on 25/08/16.
*/
public class RotatingARectangle extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Group root = new Group();
Rectangle rect = new Rectangle(190, 395, 20, 5);
rect.setFill(Color.BLUE);
Rotate rot = new Rotate(0, 200, 200);
rect.getTransforms().add(rot);
Ellipse path = new Ellipse(200, 200, 200, 200);
path.setStroke(Color.RED);
path.setFill(null);
root.getChildren().add(rect);
root.getChildren().add(path);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
Timeline line = new Timeline(30);
KeyFrame key1 = new KeyFrame(
new javafx.util.Duration(0),
new KeyValue(rot.angleProperty(), 0 )
);
KeyFrame key2 = new KeyFrame(
new javafx.util.Duration(1000),
new KeyValue(rot.angleProperty(), 360 )
);
line.getKeyFrames().addAll(key1, key2);
scene.addEventHandler(MouseEvent.MOUSE_CLICKED, evt->{
line.playFromStart();
});
}
}
I set the pivot to be the center of the elipse, then use a timeline to change the angle from 0 to 360.

JavaFX animation not working

I am trying to make an application where an object moves across the screen, only changing its x value. I am not getting any errors but it is not working when I run it. the objects are showing but the rectangle is not animating. I am not sure what to do
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
private BorderPane root;
private Stage stage;
private Scene scene;
private AnchorPane anchorPane;
private Rectangle player;
private Circle circles;
private Button up, down;
private Timeline timer;
#Override
public void start(Stage primaryStage) {
stage = primaryStage;
root = new BorderPane();
scene = new Scene(root, 600, 500); //width and height of application
stage.setScene(scene);
stage.setTitle("Hoop runner"); //text for the title bar of the window
scene.getStylesheets().add("hoop.css");
anchorPane = new AnchorPane();
anchorPane.setMaxHeight(500);
anchorPane.setMinHeight(500);
anchorPane.setMinWidth(600);
anchorPane.setMaxWidth(600);
player = new Rectangle();
circles = new Circle();
up = new Button("˄");
down = new Button("˅");
root.setCenter(new VBox(new VBox(circles),
new HBox(player)));
root.setCenter(anchorPane);
player.setX(5);
player.setY(380);
player.setHeight(80);
player.setWidth(120);
anchorPane.getChildren().add(player);
timer = new Timeline(Animation.INDEFINITE);
timer.setCycleCount(Animation.INDEFINITE);
timer.getKeyFrames().add(new KeyFrame(Duration.INDEFINITE, event -> maverick()));
timer.play();
stage.show();
}
private void maverick() {
timer.play();
System.out.println("hi");
player.setX(player.getX() + 2);
timer.play();
}
public static void main(String[] args) {
launch(args);
}
}
Use setTranslateX instead of setX if you want to position or animate Nodes.
Change timer = new Timeline(Animation.INDEFINITE) to timer = new Timeline().
Change new KeyFrame(Duration.INDEFINITE, event -> maverick()) to new KeyFrame(Duration.millis(500), event -> maverick()) (for example).
A KeyFrame has to have a point in time. If, like the example, you use 500ms, then the KeyFrame's EventHandler will get called after 500ms. Since your TimeLine has a cycleCount of INDEFINITE, it will loop and execute the KeyFrame every 500ms.

how to translate pop up windows in javaFX?

Is there any way to translate somethings like pop up windows(that are not Node) in java FX ?
for example fade transition , translate transition or any timeline transition .... .
Thank's
Create a property and use a Timeline to "animate" the property. Register a listener with the property and update the window when its value changes.
For example:
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TranslateWindowExample extends Application {
#Override
public void start(Stage primaryStage) {
Button moveButton = new Button("Move");
moveButton.setOnAction(event -> {
double currentX = primaryStage.getX() ;
DoubleProperty x = new SimpleDoubleProperty(currentX);
x.addListener((obs, oldX, newX) -> primaryStage.setX(newX.doubleValue()));
KeyFrame keyFrame = new KeyFrame(Duration.seconds(1), new KeyValue(x, currentX + 100));
Timeline animation = new Timeline(keyFrame);
animation.play();
});
StackPane root = new StackPane(moveButton);
Scene scene = new Scene(root, 250, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Can you give an example of what do you call popup window ?
For instance, you can create a new stage on the top of your main stage.
You can also use some Tooltip class to add some text over the top of your window.
If you want more classical windows, you should have a look to Alert class.
Anthony

Categories