RotationTransition Stopped in wrong angle JavaFX - javafx

I'm creating animation that will start rotating from left top corner to center of scene then go to right top corner and stop the rotation. Everything works fine but when it goes to top right corner it stop in wrong angle.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.Group;
import javafx.animation.Animation;
import javafx.animation.RotateTransition;
import javafx.animation.KeyValue;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.Interpolator;
import javafx.util.Duration;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
public class ComeWaitGo extends Application{
#Override
public void start(Stage stage){
Rectangle box = new Rectangle(0, 0, 50, 50);
RotateTransition rotate = new RotateTransition(Duration.millis(2000), box);
rotate.setCycleCount(Animation.INDEFINITE);
rotate.setByAngle(360);
rotate.setInterpolator(Interpolator.LINEAR);
rotate.play();
KeyValue one = new KeyValue(box.xProperty(), 125);
KeyValue two = new KeyValue(box.yProperty(), 100);
KeyValue three = new KeyValue(box.xProperty(), 125);
KeyValue four = new KeyValue(box.yProperty(), 100);
KeyValue five = new KeyValue(box.xProperty(), 250);
KeyValue six = new KeyValue(box.yProperty(), 0);
EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
rotate.stop();
}
};
KeyFrame frame = new KeyFrame(Duration.millis(3000), one, two);
KeyFrame frametwo = new KeyFrame(Duration.millis(8000), three, four);
KeyFrame framethree = new KeyFrame(Duration.millis(11000), stopRotate, five, six);
Timeline timeline = new Timeline();
timeline.getKeyFrames().addAll(frame, frametwo, framethree);
timeline.play();
Group root = new Group();
root.getChildren().addAll(box);
Scene scene = new Scene(root, 300, 250);
stage.setScene(scene);
stage.show();
}
}
As you can see in image. when Rectangle goes to top right corner it not showing properly. ( Red line is just showing the path of rectangle (Image Editied))
So how I can get this animation? So the rectangle at the end should be in proper angle.

Simply animate the rotate property of box using the timeline too, instead of using a seperate RotateTransition animation in addition to the Timeline animation:
KeyFrame framethree = new KeyFrame(Duration.millis(11000)
/*, stopRotate*/,
new KeyValue(box.rotateProperty(), 360d * 11000d / 2000d, Interpolator.LINEAR),
five,
six);
Alternatively combine both animations using a ParallelTransition to make sure both animations run synchronous:
// rotate.play();
...
Timeline timeline = new Timeline();
ParallelTransition transitions = new ParallelTransition(timeline, rotate);
EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
transitions.stop();
}
};
KeyFrame framethree = new KeyFrame(Duration.millis(11000), stopRotate, five, six);
timeline.getKeyFrames().addAll(frame, frametwo, framethree);
// timeline.play();
transitions.play();
complete start methods as requested
Approach 1:
#Override
public void start(Stage stage) {
Rectangle box = new Rectangle(0, 0, 50, 50);
KeyValue one = new KeyValue(box.xProperty(), 125);
KeyValue two = new KeyValue(box.yProperty(), 100);
KeyValue three = new KeyValue(box.xProperty(), 125);
KeyValue four = new KeyValue(box.yProperty(), 100);
KeyValue five = new KeyValue(box.xProperty(), 250);
KeyValue six = new KeyValue(box.yProperty(), 0);
KeyFrame frame = new KeyFrame(Duration.millis(3000), one, two);
KeyFrame frametwo = new KeyFrame(Duration.millis(8000), three, four);
KeyFrame framethree = new KeyFrame(Duration.millis(11000), five, six, new KeyValue(box.rotateProperty(), 360d * 11000d / 2000d, Interpolator.LINEAR));
Timeline timeline = new Timeline();
timeline.getKeyFrames().addAll(frame, frametwo, framethree);
timeline.play();
Group root = new Group();
root.getChildren().addAll(box);
Scene scene = new Scene(root, 300, 250);
stage.setScene(scene);
stage.show();
}
Approach 2:
#Override
public void start(Stage stage) {
Rectangle box = new Rectangle(0, 0, 50, 50);
RotateTransition rotate = new RotateTransition(Duration.millis(2000), box);
rotate.setCycleCount(Animation.INDEFINITE);
rotate.setByAngle(360);
rotate.setInterpolator(Interpolator.LINEAR);
KeyValue one = new KeyValue(box.xProperty(), 125);
KeyValue two = new KeyValue(box.yProperty(), 100);
KeyValue three = new KeyValue(box.xProperty(), 125);
KeyValue four = new KeyValue(box.yProperty(), 100);
KeyValue five = new KeyValue(box.xProperty(), 250);
KeyValue six = new KeyValue(box.yProperty(), 0);
KeyFrame frame = new KeyFrame(Duration.millis(3000), one, two);
KeyFrame frametwo = new KeyFrame(Duration.millis(8000), three, four);
Timeline timeline = new Timeline();
ParallelTransition transitions = new ParallelTransition(timeline, rotate);
EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
transitions.stop();
}
};
KeyFrame framethree = new KeyFrame(Duration.millis(11000), stopRotate, five, six);
timeline.getKeyFrames().addAll(frame, frametwo, framethree);
transitions.play();
Group root = new Group();
root.getChildren().addAll(box);
Scene scene = new Scene(root, 300, 250);
stage.setScene(scene);
stage.show();
}

One approach would be to reset the box's rotation in stopRotate():
EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
rotate.stop();
box.setRotate(0);
}
};

Related

JavaFx canvas mouse events

I would like to intercept mouse events on canvas only where I've drawn some shape, but in all other transparent area I would like to have behaviour like with property mouseTransparent true.
I can achieve that with ImageView, transparent areas doesn't intercept mouse events.
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Drawing Operations Test");
Pane root = new Pane();
root.setStyle("-fx-background-color: #C9E3AF");
root.setMinSize(1000, 1000);
root.setOnMouseClicked(event -> {
System.out.println("Clicked on root pane");
});
Canvas canvas1 = new Canvas(512, 512);
canvas1.getGraphicsContext2D().setFill(Color.BLACK);
canvas1.getGraphicsContext2D().fillRect(250, 250, 250, 250);
canvas1.setOnMouseClicked(event -> {
System.out.println("Clicked on canvas1");
});
canvas1.setPickOnBounds(false);
Canvas canvas2 = new Canvas(512, 512);
canvas2.getGraphicsContext2D().setFill(Color.RED);
canvas2.getGraphicsContext2D().fillRect(200, 200, 250, 250);
canvas2.setOnMouseClicked(event -> {
System.out.println("Clicked on canvas2");
});
canvas2.setPickOnBounds(false);
SnapshotParameters param1 = new SnapshotParameters();
param1.setFill(Color.TRANSPARENT);
WritableImage image1 = canvas1.snapshot(param1, new WritableImage(512, 512));
SnapshotParameters param2 = new SnapshotParameters();
param2.setFill(Color.TRANSPARENT);
WritableImage image2 = canvas2.snapshot(param2, new WritableImage(512, 512));
ImageView view1 = new ImageView(image1);
view1.setOnMouseClicked(event -> {
System.out.println("Clicked on view1");
});
view1.setPickOnBounds(false);
ImageView view2 = new ImageView(image2);
view2.setOnMouseClicked(event -> {
System.out.println("Clicked on view2");
});
view2.setPickOnBounds(false);
// ImageView test
// root.getChildren().addAll(view1, view2);
// Canvas test
root.getChildren().addAll(canvas1, canvas2);
Scene sc = new Scene(root);
primaryStage.setScene(sc);
primaryStage.setX(0);
primaryStage.setY(0);
primaryStage.show();
}
Is it even possible with Canvas?
As far as I'm concerned it is impossible to achieve using Canvas, but using Group and Shapes within gives you all the features of Canvas plus behaviour you expect.
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class ShapesApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Circle circle = new Circle(100);
circle.setFill(Color.BLUE);
Group group = new Group(circle);
group.setOnMouseMoved(System.out::println);
StackPane stackPane = new StackPane(group);
stackPane.setPrefSize(400, 400);
stage.setScene(new Scene(stackPane));
stage.show();
}
}

multiple windows not showing up upon execution ( 1 out of 3)

quick question,
why are my multiple windows not appearing from this code?
also any tips on how to make the circle's diameter increase only by the stage's resolution when the window is increased in size; anyway of doing this internally through "circ3."
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;
public class Circles extends Application {
#Override
public void start(Stage primaryStage){
Pane pane = new Pane();
Circle circ = new Circle();
circ.setStroke(Color.DARKBLUE);
circ.setFill(Color.YELLOW);
circ.centerXProperty().bind(pane.widthProperty().divide(10));
circ.centerYProperty().bind(pane.heightProperty().subtract(20));
circ.centerXProperty().bind(pane.widthProperty().subtract(20));
circ.setRadius(20);
pane.getChildren().add(circ);
Scene scene = new Scene(pane, 500, 200);
primaryStage.setTitle("Bottom Right");
primaryStage.setScene(scene);
primaryStage.show();
Pane pane2 = new Pane();
Circle circ2 = new Circle();
circ2.setStroke(Color.PEACHPUFF);
circ2.setFill(Color.YELLOWGREEN);
circ2.centerXProperty().bind(pane2.widthProperty().divide(2));
circ2.centerYProperty().bind(pane2.heightProperty().subtract(20));
circ2.setRadius(20);
pane2.getChildren().add(circ2);
Scene scene2 = new Scene(pane2, 200, 500);
primaryStage.setTitle("Bottom Centered");
primaryStage.setScene(scene2);
primaryStage.show();
Pane pane3 = new Pane();
Circle circ3 = new Circle();
circ3.setStroke(Color.PEACHPUFF);
circ3.setFill(Color.YELLOWGREEN);
circ3.centerXProperty().bind(pane3.widthProperty().subtract(150));
circ3.centerYProperty().bind(pane3.heightProperty().divide(2));
circ3.setRadius(150);
//size (circle diameter) needs to scale with width resolution
pane3.getChildren().add(circ3);
//boilerplate
Scene scene3 = new Scene(pane3, 300, 500);
primaryStage.setTitle("Radius / Width ");
primaryStage.setScene(scene3);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
You can make the circle change size with the window size using bindings:
Pane pane3 = new Pane();
Circle circ3 = new Circle();
circ3.setStroke(Color.PEACHPUFF);
circ3.setFill(Color.YELLOWGREEN);
circ3.centerXProperty().bind(pane3.widthProperty().divide(2));
circ3.centerYProperty().bind(pane3.heightProperty().divide(2));
circ3.radiusProperty().bind(pane3.widthProperty().divide(2));

how to resize button in a animation javafx

I'm using an animation in javafx so when I click on button it move with an animation but I want to also resize it (It should become smaller and smaller).
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
/*Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));*/
AnchorPane root=new AnchorPane();
Timeline timeline = new Timeline();
Button button = new Button();
timeline.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO,
new KeyValue(button.translateXProperty(), 500),
new KeyValue(button.translateYProperty(), 500)),
new KeyFrame(Duration.seconds(.5), // set end position at 40s
new KeyValue(button.translateXProperty(), 200),
new KeyValue(button.translateYProperty(), 200)));
timeline.play();
root.getChildren().addAll(button);
primaryStage.show();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 800, 800));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
One possibility is to animate the node's scaleProperties:
timeline.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO,
new KeyValue(button.translateXProperty(), 500),
new KeyValue(button.translateYProperty(), 500),
new KeyValue(button.scaleXProperty(), 1),
new KeyValue(button.scaleYProperty(), 1)),
new KeyFrame(Duration.seconds(.5), // set end position at 40s
new KeyValue(button.translateXProperty(), 200),
new KeyValue(button.translateYProperty(), 200),
new KeyValue(button.scaleXProperty(), .4),
new KeyValue(button.scaleYProperty(), .4)));
timeline.play();

JavaFX Circle object not registering mouse events properly

I want the user to be able to drag-move the circles around the pane. The circles dont seem to register (almost) no mouse events (as defined in the end). I have the same exact code for an empty pane it works just fine. Also if I change
circle1.setOnMouseDragged
to
paneForCircles.setOnMouseDragged
it works just fine but its not what I want because I need to manipulate both circles. Any ideas ? I would appreciate it if you could also tell me how to hide the part of the circle that overlaps with the adjacent elements if its center is too close to the pane border.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Ex168 extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Circle circle1 = new Circle(30);
Circle circle2 = new Circle(35);
circle1.setCenterX(100);
circle1.setCenterY(100);
circle2.setCenterX(150);
circle2.setCenterY(120);
circle1.setStroke(Color.BLACK);
circle1.setFill(null);
circle2.setStroke(Color.BLACK);
circle2.setFill(null);
VBox vBoxForScene = new VBox(5);
vBoxForScene.setPadding(new Insets(5));
vBoxForScene.setAlignment(Pos.TOP_CENTER);
Pane paneForCircles = new Pane();
paneForCircles.setStyle("-fx-border-color: black");
vBoxForScene.heightProperty().addListener(ov -> paneForCircles.setPrefHeight(vBoxForScene.heightProperty().divide(1.2).doubleValue()));
paneForCircles.setPrefHeight(300);
HBox hBoxForFields = new HBox(5);
hBoxForFields.setAlignment(Pos.CENTER);
hBoxForFields.setSpacing(5);
// VBofForLeftFields
VBox vBoxForLeftFields = new VBox(5);
vBoxForLeftFields.setAlignment(Pos.CENTER_LEFT);
Label lblCircle1 = new Label("Enter Circle 1 info");
lblCircle1.setAlignment(Pos.TOP_LEFT);
TextField tfCircle1CenterX = new TextField();
tfCircle1CenterX.textProperty().bind(circle1.centerXProperty().asString());
TextField tfCircle1CenterY = new TextField();
tfCircle1CenterY.textProperty().bind(circle1.centerYProperty().asString());
TextField tfCircle1Radius = new TextField();
tfCircle1Radius.textProperty().bind(circle1.radiusProperty().asString());
tfCircle1CenterX.setPrefColumnCount(5);
tfCircle1Radius.setPrefColumnCount(5);
tfCircle1CenterY.setPrefColumnCount(5);
Label lblCenterX = new Label("Center x:", tfCircle1CenterX);
Label lblCenterY = new Label("Center x:", tfCircle1CenterY);
Label lblCircle1Radius= new Label("Radius: ", tfCircle1Radius);
lblCenterX.setContentDisplay(ContentDisplay.RIGHT);
lblCenterY.setContentDisplay(ContentDisplay.RIGHT);
lblCircle1Radius.setContentDisplay(ContentDisplay.RIGHT);
//VBoxForRightFields
VBox vBoxForRightFields = new VBox(5);
Label lblCircle2 = new Label("Enter Circle 2 info");
TextField tfCircle2CenterX = new TextField();
TextField tfCircle2CenterY = new TextField();
TextField tfCircle2Radius = new TextField();
tfCircle2CenterX.setPrefColumnCount(5);
tfCircle2CenterX.textProperty().bind(circle2.centerXProperty().asString());
tfCircle2Radius.setPrefColumnCount(5);
tfCircle2Radius.textProperty().bind(circle2.radiusProperty().asString());
tfCircle2CenterY.setPrefColumnCount(5);
tfCircle2CenterY.textProperty().bind(circle2.centerYProperty().asString());
Label lblCenter2X = new Label("Center x:", tfCircle2CenterX);
Label lblCenter2Y = new Label("Center x:", tfCircle2CenterY);
Label lblCircle2Radius= new Label("Radius: ", tfCircle2Radius);
lblCenter2X.setContentDisplay(ContentDisplay.RIGHT);
lblCenter2Y.setContentDisplay(ContentDisplay.RIGHT);
lblCircle2Radius.setContentDisplay(ContentDisplay.RIGHT);
vBoxForRightFields.getChildren().addAll(lblCircle2, lblCenter2X, lblCenter2Y, lblCircle2Radius);
vBoxForLeftFields.getChildren().addAll(lblCircle1, lblCenterX, lblCenterY, lblCircle1Radius);
hBoxForFields.getChildren().addAll(vBoxForLeftFields, vBoxForRightFields);
Label lblResult = new Label("Do the two circles intersect?");
Button btReDrawCircles = new Button("Redraw Circles");
vBoxForScene.getChildren().addAll(lblResult, paneForCircles, hBoxForFields, btReDrawCircles);
circle1.setOnMouseDragged(e -> {
System.out.println(e.getX());
circle1.setCenterX(e.getX());
circle1.setCenterY(e.getY());
});
circle2.setOnMouseDragged(e -> {
circle2.setCenterX(e.getX());
circle2.setCenterY(e.getY());
});
paneForCircles.getChildren().addAll(circle1, circle2);
Scene scene = new Scene(vBoxForScene);
primaryStage.setScene(scene);
primaryStage.setMinHeight(400);
primaryStage.setMinWidth(340);
primaryStage.setAlwaysOnTop(true);
primaryStage.show();
circle1.requestFocus();
}
}
This code on the other hand, which is supposed to do the same thing, works perfectly
public class CircleDraggingSample extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final double RADIUS=10;
Pane pane = new Pane();
pane.setPrefHeight(300);
pane.setPrefWidth(300);
Circle circle1 = new Circle(RADIUS);
circle1.setCenterX(30);
circle1.setCenterY(30);
Circle circle2 = new Circle(RADIUS);
circle2.setCenterX(100);
circle2.setCenterY(100);
Line line = new Line();
line.endXProperty().bind(circle2.centerXProperty());
line.endYProperty().bind(circle2.centerYProperty());
line.startXProperty().bind(circle1.centerXProperty());
line.startYProperty().bind(circle1.centerYProperty());
pane.getChildren().addAll(circle1, circle2, line);
circle2.setOnMouseDragged(e -> {
circle2.setCenterX(e.getX());
circle2.setCenterY(e.getY());
});
circle1.setOnMouseDragged(e -> {
circle1.setCenterX(e.getX());
circle1.setCenterY(e.getY());
});
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Even though you have posted an example, I'd rather show you a way with mine how it is done in general. There are several ways, this is one that works:
public class DragNodes extends Application {
public static List<Circle> circles = new ArrayList<Circle>();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Circle circle1 = new Circle( 100, 100, 50);
circle1.setStroke(Color.GREEN);
circle1.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.3));
Circle circle2 = new Circle( 200, 200, 50);
circle2.setStroke(Color.BLUE);
circle2.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3));
Line line = new Line();
line.setStrokeWidth(20);
// binding
line.startXProperty().bind(circle1.centerXProperty());
line.startYProperty().bind(circle1.centerYProperty());
line.endXProperty().bind(circle2.centerXProperty());
line.endYProperty().bind(circle2.centerYProperty());
MouseGestures mg = new MouseGestures();
mg.makeDraggable( circle1);
mg.makeDraggable( circle2);
mg.makeDraggable( line);
root.getChildren().addAll(circle1, circle2, line);
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.show();
}
public static class MouseGestures {
class DragContext {
double x;
double y;
}
DragContext dragContext = new DragContext();
public void makeDraggable( Node node) {
node.setOnMousePressed( onMousePressedEventHandler);
node.setOnMouseDragged( onMouseDraggedEventHandler);
node.setOnMouseReleased(onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if( event.getSource() instanceof Circle) {
Circle circle = ((Circle) (event.getSource()));
dragContext.x = circle.getCenterX() - event.getSceneX();
dragContext.y = circle.getCenterY() - event.getSceneY();
} else {
Node node = ((Node) (event.getSource()));
dragContext.x = node.getTranslateX() - event.getSceneX();
dragContext.y = node.getTranslateY() - event.getSceneY();
}
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if( event.getSource() instanceof Circle) {
Circle circle = ((Circle) (event.getSource()));
circle.setCenterX( dragContext.x + event.getSceneX());
circle.setCenterY( dragContext.y + event.getSceneY());
} else {
Node node = ((Node) (event.getSource()));
node.setTranslateX( dragContext.x + event.getSceneX());
node.setTranslateY( dragContext.y + event.getSceneY());
}
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
}
};
}
}
It shows how to drag circles and bind another node (the line) so that it gets modified as well when you drag the circles. You can also drag the line separately which is a Node and handled differently.
In case you still got problems let me know.
As a general note, it's always advisable to add this to a node in order to understand which events happen:
node.addEventFilter(Event.ANY, e -> System.out.println( e));
and then check the console output while you do something on screen.
Regarding your main problem: You mustn't set Fill to null. In that case the click event won't get registered. You should use Color.TRANSPARENT instead. You can verify the event difference with the above mentioned method.

Fade Effect with JavaFX

Im trying to realize a special FadeTransition effect. But I have no idea how I can manage it. For some node I would like to increase the opacity from left to right (for example in Powerpoint, you can change the slides with such an effect). Here is an easy example for rectangles. But the second one should fadeIn from left to right (the opacity should increase on the left side earlier as on the right side). With timeline and KeyValues/KeyFrames I found also no solution.
Thanks in advance.
Rectangle rec2;
#Override
public void start(Stage stage) {
Group root = new Group();
Scene scene = new Scene(root, 400, 300, Color.BLACK);
stage.setTitle("JavaFX Scene Graph Demo");
Pane pane = new Pane();
Button btnForward = new Button();
btnForward.setText(">");
btnForward.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
FadeTransition ft = new FadeTransition(Duration.millis(2000), rec2);
ft.setFromValue(0.);
ft.setToValue(1.);
ft.play();
}
});
Rectangle rec1 = new Rectangle(0, 0, 300,200);
rec1.setFill(Color.RED);
rec2 = new Rectangle(100, 50, 100,100);
rec2.setFill(Color.GREEN);
rec2.setOpacity(0.);
pane.getChildren().addAll(rec1,rec2);
root.getChildren().add(pane);
root.getChildren().add(btnForward);
stage.setScene(scene);
stage.show();
}
Define the fill of the rectangle using css with a linear gradient which references looked-up colors for the left and right edges of the rectangle. (This can be inline or in an external style sheet.)
Define a couple of DoublePropertys representing the opacities of the left and right edge.
Define the looked-up colors on the rectangle or one of its parents using an inline style bound to the two double properties.
Use a timeline to change the values of the opacity properties.
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class FadeInRectangle extends Application {
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root, 400, 300, Color.BLACK);
primaryStage.setTitle("JavaFX Scene Graph Demo");
Pane pane = new Pane();
Rectangle rec1 = new Rectangle(0, 0, 300,200);
rec1.setFill(Color.RED);
Rectangle rec2 = new Rectangle(100, 50, 100,100);
rec2.setStyle("-fx-fill: linear-gradient(to right, left-col, right-col);");
final DoubleProperty leftEdgeOpacity = new SimpleDoubleProperty(0);
final DoubleProperty rightEdgeOpacity = new SimpleDoubleProperty(0);
root.styleProperty().bind(
Bindings.format("left-col: rgba(0,128,0,%f); right-col: rgba(0,128,0,%f);", leftEdgeOpacity, rightEdgeOpacity)
);
Button btnForward = new Button();
btnForward.setText(">");
btnForward.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(leftEdgeOpacity, 0)),
new KeyFrame(Duration.ZERO, new KeyValue(rightEdgeOpacity, 0)),
new KeyFrame(Duration.millis(500), new KeyValue(rightEdgeOpacity, 0)),
new KeyFrame(Duration.millis(1500), new KeyValue(leftEdgeOpacity, 1)),
new KeyFrame(Duration.millis(2000), new KeyValue(rightEdgeOpacity, 1)),
new KeyFrame(Duration.millis(2000), new KeyValue(leftEdgeOpacity, 1))
);
timeline.play();
}
});
pane.getChildren().addAll(rec1,rec2);
root.getChildren().add(pane);
root.getChildren().add(btnForward);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Resources