Rotation through images using JAVA FX - animation

Essentially I'm trying to make a glowing warning image.
Starts just being a red triangle, but then emits a glow, then goes back to a red triangle.
But I'm trying to figure out a way to implement it.
I thought of using timelines, but it will only show the last picture, and stay on it.
I've replaced my Imaged with ones publicly available.
With these images it should come up "Number 1" for 2 seconds, "Number 2" for 2 seconds, "number 3" for 2 seconds, then go back to number 1 and repeat indefinitely.
Other than my way, if someone has a better way to make my objective happen in a different way with Java FX (That isn't too complex, I'm pretty new to Java FX). I'm all ears
Thanks again!
Here is the code I've fiddled with.
public class GlowEffect extends Application {
#Override
public void start(Stage primaryStage) {
Image img1 = new Image("http://clipart-library.com/images/dc9rEEbdi.jpg");
Image img2 = new Image("http://clipart-library.com/data_images/356167.png");
Image img3 = new Image("http://clipart-library.com/data_images/123556.png");
ImageView imgview1 = new ImageView();
imgview1.setX(0);
imgview1.setY(0);
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(2), e -> imgview1.setImage(img1)),
new KeyFrame(Duration.seconds(2), e -> imgview1.setImage(img2)),
new KeyFrame(Duration.seconds(2), e -> imgview1.setImage(img3))
);
timeline.setCycleCount(Animation.INDEFINITE);
Pane pane = new Pane(imgview1);
Scene scene = new Scene(pane, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
timeline.play();
}
public static void main(String[] args) {
launch(args);
}
}

Related

Javafx relocate and rotate

i have an node in javafx which are moving in a timeline.
Now i want rotate the node also.
I tried it but everytime the node doesn't hold the path anymore and "fly away". Is there a way to relcate and rotate (I tried it with rotatetransition)?
Edit:
That is my View -Class
public class MyView extends ImageView{
public MyView (Image image) {
super(image);
RotateTransition transition = new RotateTransition();
transition.setCycleCount(Animation.INDEFINITE);
transition.setNode(this);
transition.setDuration(Duration.millis(10));
transition.setFromAngle(5);
transition.setToAngle(5;
transition.setAutoReverse(true);
transition.play(); // */
}
}
On another class i have this:
private void startMoveAnimation(MyView[] views) {
x++;
y++;
this.timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
moveEvent = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
for(View view: views){
view.relocate(x,y);
}
}
}
};
KeyFrame moveKeyFrame = new KeyFrame(Duration.millis(SPEED), moveEvent);
timeline.getKeyFrames().add(moveKeyFrame);
timeline.play(); // */
}
x and y are double values.
Using transforms gives you better control of the order of the transformations. Furthermore some transfroms allow you to specify a pivot point, which is not possible for e.g. the Node.rotate property. Transforms in a list are applied "right to left". (The transform with the highest index is applied first).
The following example shows how to move a rectangle rotating arount its own center (even though the cycle resets to the original position instead of continuously moving in the same direction, but the properties of the transforms can be animated independently in arbitrary ways):
#Override
public void start(Stage primaryStage) {
Rectangle view = new Rectangle(100, 100);
// pivot point = center of rect
Rotate rotate = new Rotate(0, 50, 50);
Translate translate = new Translate();
// rotate first, then move
view.getTransforms().addAll(translate, rotate);
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(translate.xProperty(), 0d),
new KeyValue(translate.yProperty(), 0d), new KeyValue(rotate.angleProperty(), 0d)),
new KeyFrame(Duration.seconds(2), new KeyValue(translate.xProperty(), 300d),
new KeyValue(translate.yProperty(), 500d), new KeyValue(rotate.angleProperty(), 360d)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
Pane root = new Pane(view);
Scene scene = new Scene(root, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
That's what I would try first:
Put the node into a Group. Add the Group to the parent instead of the node. Do the translate animation on the Group and do the rotate animation on the node itself. This is just a first guess which I cannot try out because you haven't provided a minimal reproducible example.

Difference between Timeline's stop() and jumpTo("end")

Could somebody explain me the difference between timeline.stop() and timeline.jumpTo("end")?
Timeline.stop() halts the animation and makes sure Timeline.play() starts form the beginning of the animation; no more updates for the "current run" are done.
timeline.jumpTo("end") goes to the mark "end" which is positioned at the end of the animation. This has the same effect as timeline.jumpTo(timeline.getTotalDuration()). Any effects of the animation arriving at that time are executed.
You can observe the different behavior in the following example:
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Play / (Stop/Jump)");
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(btn.translateXProperty(), 0d)),
new KeyFrame(Duration.seconds(10), new KeyValue(btn.translateXProperty(), 200d))
);
btn.setOnAction((ActionEvent event) -> {
if (timeline.getStatus() == Animation.Status.RUNNING) {
// timeline.jumpTo("end");
timeline.stop();
} else {
timeline.play();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
timeline.jumpTo("end") moves the Button to the end point of the animation, timeline.stop() stops the Button in it's current position.

How to have selectable images from image gallery in javafx?

I am making an image gallery. I am using javafx 8 along with scene builder for GUI. I want the user to have choice of selecting images from a gallery: I want to have clickable and selectable images in the gallery. I also want to note the sequence of those selected images, i.e. which one was selected first and which one was selected last. I have made the gallery but I was wondering what I would do to make the images clickable and get the images selected, noting their sequence? I don't want to use checkboxes with the images.
You can add a setOnMouseClicked handler on each ImageView.
Here is a code example of what I mean:
public class ClickableImage extends Application {
private ArrayList<String> clickedImages = new ArrayList<>();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
String imgUrl = getClass().getResource("image.png").toExternalForm();
assert imgUrl != null;
Image img = new Image(imgUrl);
assert img != null;
BorderPane root = new BorderPane();
ImageView imgView = new ImageView(img);
imgView.setUserData(imgUrl);
root.setCenter(imgView);
Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.setTitle("ClickableImage");
primaryStage.show();
//-------------
imgView.setOnMouseClicked(e -> {
String clickedImgUrl = (String)((ImageView)e.getSource()).getUserData();
System.out.println("Image was clicked: " + clickedImgUrl);
clickedImages.add(clickedImgUrl);
});
}
}

How to manage element precedence in JavaFX2?

Given this code:
#Override
public void start(final Stage stage)
{
final StackPane root = new StackPane();
final Region r1 = new Region(), r2 = new Region(), r3 = new Region();
r1.setMaxSize(400, 400);
r1.setStyle("-fx-background-color: yellow");
StackPane.setAlignment(r1, Pos.TOP_LEFT);
r2.setMaxSize(400, 400);
r2.setStyle("-fx-background-color: black");
StackPane.setAlignment(r2, Pos.TOP_RIGHT);
r3.setMaxSize(400, 400);
r3.setStyle("-fx-background-color: blue");
StackPane.setAlignment(r3, Pos.BOTTOM_CENTER);
root.getChildren().addAll(r1, r2 ,r3);
final Scene scene = new Scene(root, 600, 600);
stage.setScene(scene);
stage.show();
}
The output is the following:
Is there any easy way to control element precedence, without removing and re-adding all the elements that follow in the correct order? What I want to do, in this particular case, is make the element with the yellow background to overlay the other two, thus resulting in this:
The Scene Builder can move elements with CTRL+([|]). The only way that I can think of currently though, when it comes to doing this in code, is getting the children of the root element and doing pairs of remove/add in the correct order. Is there any other way, like, maybe, some property that manages overlay priority? Thank you.

How can I load Computer Directory images in JAVAFX

I am trying to load my computer folder images into a wall of thumbnails. I read on a thread from another forum that ImageView "url" instance variable does not support system paths. I tried with the solution there, but it throws an exception: java.lang.OutOfMemoryError: Java heap space as it keeps reading the file.
another problem is it keeps giving me warning of using package javafx.ext -> SwingUtils.toFXImage method.
I have also tried to input the URL like that:
"file://localhost//Users/USER/Pictures/Camera/test/1.JPG"
I tried to display a number of images, but it always only displays 3 to 4 images.
I checked with the error function given from ImageView, it does not indicate that the reading of my images encountered an error.
Are there any alternatives?
Code
function load() {
println("RUNTIME {Runtime.getRuntime().maxMemory()}");
System.gc();
Runtime.getRuntime().freeMemory();
//MAC Folder PATH
var path: String = "/Users/username/Pictures/camera/test/1.JPG";;
var file: File = new File(path);
//http://download.oracle.com/docs/cd/E17802_01/javafx/javafx/1.3/docs/api/javafx.ext.swing/javafx.ext.swing.SwingUtils.html
//public toFXImage(image: java.awt.image.BufferedImage) : Image
//Creates a JavaFX Image from a BufferedImage.
img = SwingUtils.toFXImage(ImageIO.read(file));
}
It is not clear exactly what you are trying to do. If you are talking about JavaFX 2.0, the following code works. If you are loading a lot of images and need to conserve memory, you only have to create enough ImageView's for the number you want to display at one time. Then as you page through the images, you can swap out the Image object contained in the ImageView.
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
File file = new File("/System/Library/CoreServices/loginwindow.app/Contents/Resources/LogOut.png");
Image image = new Image(file.toURI().toString());
ImageView iv = new ImageView(image);
root.getChildren().add(iv);
primaryStage.setScene(scene);
primaryStage.show();
}
its simple: open a image with a browser and copy the whole url of the pic and paste it as a parameter of the Image object. DO NOT REMOVE "file///:" because this makes the image loadable. you will get your other logic from there. happy coding e.g
Image image = new Image("file:///C:/Users/Nigel/Desktop/my_image.png");
ImageView imgview = new ImageView(image);
None of the previous answers worked for me. However, this one, which I saw a while back but can't find an original link from, works flawlessly.
#Override
public void start(Stage primaryStage) throws Exception {
//create a pane to hold the image views
Pane pane = new HBox(10);
pane.setPadding(new Insets(5,5,5,5));
//create the image to be used!
Image image = new Image("/Content/vortex.jpg");
//set some custom properties and add an image
ImageView imageView = new ImageView(image);
imageView.setFitHeight(100);
imageView.setFitWidth(100);
pane.getChildren().add(imageView);
//add the second image view with this image and no custom properties
pane.getChildren().add(new ImageView(image));
ImageView imageView2 = new ImageView(image);
imageView2.setRotate(45);
pane.getChildren().add(imageView2);
Scene scene = new Scene(pane, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
The key is that when you create the image, START the path with a '/' (ie: "/Content/vortex.jpg"). Note that in this setup, the root folder is the src folder in most IDEs.
sorry if my answer came a little bit late but that was my approach and it works 100% wherever you are putting your file
1.assign your image to File
2.parse the File to URI
3.assign the uri.toString() to the image
ex code:
File imageFile = new File("path/to/image/outside/your/jar/awesomeless.jpg");
String fileLocation = imageFile.toURI().toString();
Image fxImage = new Image(fileLocation);
or you can simply put it all together like this:
Image fxImage = new Image(new File("path/.../awesomemore.jpg").toURI().toString());
and please if anyone knows a better approach let us know!
Another solution is to pass the InputStream into the Image class constructor; and is working...
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
java.io.FileInputStream fis = new FileInputStream("/System/Library/CoreServices/loginwindow.app/Contents/Resources/LogOut.png");
ImageView iv = new ImageView(new Image(fis));
root.getChildren().add(iv);
primaryStage.setScene(scene);
primaryStage.show();
}

Resources