import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Arc;
import javafx.scene.paint.Color;
import javafx.scene.control.Button;
import javafx.scene.Group;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.animation.PathTransition;
import javafx.util.Duration;
import javafx.scene.shape.Ellipse;
public class MovingFourFans extends Application
{
private Button btPause = new Button("Pause");
private Button btResume = new Button("Resume");
private Button btReverse = new Button("Reverse");
private Circle fanPanel;
private Ellipse fanPath;
private Arc fan1;
private Arc fan2;
private Arc fan3;
private Arc fan4;
private BorderPane uiContainer;
private HBox buttonContainer;
private PathTransition pt = new PathTransition();
#Override
public void start(Stage primaryStage)
{
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane, 400, 500);
buttonContainer = new HBox(btPause, btResume, btReverse);
buttonContainer.setAlignment(Pos.CENTER);
Group group = new Group();
pane.setCenter(group);
pane.setBottom(buttonContainer);
// include a path transition with a circle inside instead
fanPanel = new Circle(Math.min(pane.getWidth(), pane.getHeight()) / 4);
fanPanel.setFill(Color.WHITE);
fanPanel.setStroke(Color.BLACK);
fanPath = new Ellipse(fanPanel.getRadius() / 100, fanPanel.getRadius() / 100);
fanPath.setVisible(true);
fanPath.setFill(Color.WHITE);
fanPath.setStroke(Color.BLACK);
fan1 = new Arc();
fan1.setType(ArcType.ROUND);
fan1.setRadiusX(fanPanel.getRadius() - 10);
fan1.setRadiusY(fanPanel.getRadius() - 10);
fan1.setStartAngle(80);
fan1.setLength(-10);
fan1.setFill(Color.RED);
group.getChildren().addAll(fanPanel, fanPath, fan1);
pt.setPath(fanPath);
pt.setNode(fan1);
pt.setCycleCount(Timeline.INDEFINITE);
pt.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
pt.setDuration(Duration.seconds(3));
pt.setAutoReverse(false);
pt.play();
btPause.setOnAction(e -> pt.pause());
btResume.setOnAction(e -> pt.play());
primaryStage.setTitle("Control Moving Fan");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}
I'm having a problem trying to create an animation of a fan with four wings with Javafx. I know how to make the buttons work but for the animation every time I start it, the fans moving along the circle path that I created with its middle section not the tip of the section. Because of this the animation doesn't look correct. Does anyone know a fix to this or what method I can use to create the correct animation for this? In this code I only made one wing for test and there are 3 wings left. The screenshot for what I currently have is below.
Related
I'm trying to understand the driver file I've been given for a certain problem I'm working on. I just started learning javafx and I'm try to create a shape inside the driver file, but the extra code of initializing, mouse events, etc. are in the source file. I created a function that returns the initialized X for the rectangle and a system.out.println in my driver file so I know they are connected. However whenever I run my driver file, I get a blank screen without the shape on it. Could someone tell me what I'm doing wrong with the scene/root/stage showing.
Heres my Code:
Multishape.java:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Multishape extends Group {
//Declaring variables here gives them greater scope
private Rectangle rectangle;
private Circle circle;
Group root = new Group();
public Multishape (double x, double y, double len){
rectangle = new Rectangle(len, len, Color.BLUE);
rectangle.setX(x);
rectangle.setY(y);
circle = new Circle(len, Color.RED);
}
//#Override
public void start(Stage primaryStage) {
//rectangle.setOnMouseClicked(handleMouseClick);//Set mouse click handler
//circle.setOnMouseClicked(handleMouseClick);//Set mouse click handler
root.getChildren().add(rectangle);//Set initial shape.
Scene scene = new Scene(root, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
double getLen(){
return (rectangle.getX());
}
}
MultishapeDriver.java:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.input.KeyEvent;
import javafx.event.EventHandler;
public class MultishapeDriver extends Application
{
public static void main(String[] args)
{
launch(args);
}
public void start(Stage stage)
{
stage.setTitle("Multishape lab");
Group root = new Group();
Multishape shape = new Multishape(320, 240, 40);
root.getChildren().add(shape);
//stage.addEventHandler(KeyEvent.KEY_TYPED, shape.getKeyHandler());
System.out.println(shape.getLen());
stage.setScene(new Scene(root, 640, 480));
stage.show();
}
}
Your Multishape is a container of type Group.
But in its constructor, you only create 2 objects, you never adde them to your multishape.
Sou you'll need to add them with getChildren().add(rectangele), etc to your multishape.
Your Multishape constructor would then look like this:
public Multishape (double x, double y, double len){
rectangle = new Rectangle(len, len, Color.BLUE);
rectangle.setX(x);
rectangle.setY(y);
circle = new Circle(len, Color.RED);
getChildren().add(rectangle);
getChildren().add(circle);
}
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.
I am using RotateTransiton to rotate a line, but it seems to rotate through center of the line. I would like to rotate it with pivot as one end of the line. How to do this?
The RotateTransition works by changing the rotate property, which - as you have observed - defines a rotation around the center of the Node.
If you want to rotate around a different point, define a Rotate transform, set its pivot, add it to the line's list of transforms, and use a Timeline to manipulate its angle.
Here's an example:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
public class RotateLineAboutEnd extends Application {
#Override
public void start(Stage primaryStage) {
Line line = new Line(200, 200, 200, 350);
Pane pane = new Pane(line);
Rotate rotation = new Rotate();
rotation.pivotXProperty().bind(line.startXProperty());
rotation.pivotYProperty().bind(line.startYProperty());
line.getTransforms().add(rotation);
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(rotation.angleProperty(), 0)),
new KeyFrame(Duration.seconds(1), new KeyValue(rotation.angleProperty(), 360)));
Button button = new Button("Rotate");
button.setOnAction(evt -> timeline.play());
button.disableProperty().bind(timeline.statusProperty().isEqualTo(Animation.Status.RUNNING));
HBox controls = new HBox(button);
controls.setAlignment(Pos.CENTER);
controls.setPadding(new Insets(12));
BorderPane root = new BorderPane(pane, null, null, controls, null);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
(on JavaFX 2.2 and JavaFX 8)
The best way in my opinion is translating the layoutBounds of the node (which contains the pivot point) and translating the node itself the opposite way.
An example:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Group root = new Group();
primaryStage.setScene(new Scene(root, 140, 140));
Rectangle rect = new Rectangle(1, 1, 40, 40);
// comment movePivot to get the default rotation
movePivot(rect, -20, -20);
RotateTransition rt = new RotateTransition(Duration.seconds(4),rect);
rt.setToAngle(720);
rt.setCycleCount(Timeline.INDEFINITE);
rt.setAutoReverse(true);
rt.play();
primaryStage.show();
}
// this is the function you want
private void movePivot(Node node, double x, double y){
node.getTransforms().add(new Translate(-x,-y));
node.setTranslateX(x); node.setTranslateY(y);
}
public static void main(String[] args) {
launch(args);
}
}
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
Suppose we have a rectangle called r
Rectangle r = new Rectangle(40, 20);
and an image called image
Image image = new Image("...src for image");
How do I fit the image inside the rectangle? Also, how can I make the image move if the rectangle moves too? How do I do the same thing for a circle? Code examples are greatly appreciated.
P.S. Jewelsea, I'm waiting for you, lol!
if you want to fill Rectangle by image, you can follow this:-
in your fxml file add a Circle
<Rectangle fx:id="imgMenuUser" />
And in your Controller
#FXML
private Rectangle rectangle;
Image img = new Image("/image/rifat.jpg");
rectangle.setFill(new ImagePattern(img));
How do I fit the image inside the rectangle?
Put the shape and the image in a StackPane.
Also, how can I make the image move if the rectangle moves too?
Just move the StackPane.
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Point2D;
import javafx.stage.Stage;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
StackPane imageContainer = new StackPane();
ImageView image = new ImageView(...);
imageContainer.getChildren().addAll(new Rectangle(64, 48, Color.CORNFLOWERBLUE), image);
enableDragging(imageContainer);
root.getChildren().add(imageContainer);
Scene scene = new Scene(root,800,600);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
private void enableDragging(Node node) {
final ObjectProperty<Point2D> mouseAnchor = new SimpleObjectProperty<>();
node.setOnMousePressed( event -> mouseAnchor.set(new Point2D(event.getSceneX(), event.getSceneY())));
node.setOnMouseDragged( event -> {
double deltaX = event.getSceneX() - mouseAnchor.get().getX();
double deltaY = event.getSceneY() - mouseAnchor.get().getY();
node.relocate(node.getLayoutX()+deltaX, node.getLayoutY()+deltaY);
mouseAnchor.set(new Point2D(event.getSceneX(), event.getSceneY()));;
});
}
public static void main(String[] args) {
launch(args);
}
}