why does while() loop not work on pathTransition? - javafx

I've been trying to make my pathTransition loop but it doesn't work. I have already tried with a while loop but nothing happens. "boom" runs the path once and then stops. I would like the "boom" to choose a new path each time.
int i = 1;
while(i < 5){
Path path = new Path();
double x = (new Random().ints(-100,400 + 1).iterator().next());
path.getElements().add (new MoveTo (x, -190));
path.getElements().add (new LineTo(x, 300));
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(10000));
pathTransition.setNode(boom);
pathTransition.setPath(path);
pathTransition.setOrientation(OrientationType.NONE);
pathTransition.setAutoReverse(false);
pathTransition.play();
i++;

You want to add all your PathTransitions to a SequentialTransition like this:
import java.util.Random;
import javafx.animation.PathTransition;
import javafx.animation.SequentialTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.stage.Stage;
import javafx.util.Duration;
public class PathLoop extends Application {
Node boom;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Button goButton = new Button("Go");
goButton.setOnAction(this::doAnimation);
boom = new Circle(20, Color.RED);
AnchorPane playfield = new AnchorPane(boom);
playfield.setPrefSize(600, 600);
AnchorPane.setLeftAnchor(boom, 100.0);
AnchorPane.setTopAnchor(boom, 300.0);
VBox root = new VBox(goButton, playfield);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("Sequential Transition");
primaryStage.show();
}
private void doAnimation(ActionEvent e) {
Random rng = new Random();
SequentialTransition seqTransition = new SequentialTransition(boom);
int i = 1;
while(i < 5){
Path path = new Path();
double x = (rng.ints(-100,400 + 1).iterator().next());
path.getElements().add (new MoveTo(x, -190));
path.getElements().add (new LineTo(x, 300));
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(10000));
pathTransition.setNode(boom);
pathTransition.setPath(path);
pathTransition.setOrientation(PathTransition.OrientationType.NONE);
pathTransition.setAutoReverse(false);
seqTransition.getChildren().add(pathTransition);
i++;
}
seqTransition.play();
}
}

Related

Removing node at particular column of GridPane with mousepress

I am trying to remove multiple nodes, one at a time, from a GridPane by first getting the coordinates on mousepress, then using gridpane.getChildren().remove(column) using column as the index to remove. This works as expected if I start with an arbitrary index and then mousepress on a lesser valued index, however it does not work if I try to mousepress on a greater valued index, the mousepress value retains the previous value of the node.
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DominoMain extends Application {
GridPane humanHand = new GridPane();
ImageView imageView;
int column;
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane root = new AnchorPane();
List<ImageView> tiles = new ArrayList<>();
String[] imageResources = new String[] {
"00.jpg", "10.jpg", "11.jpg", "20.jpg", "21.jpg", "22.jpg",
"30.jpg", "31.jpg", "32.jpg", "33.jpg", "40.jpg", "41.jpg",
"42.jpg", "43.jpg", "44.jpg", "50.jpg", "51.jpg", "52.jpg",
"53.jpg", "54.jpg", "55.jpg", "60.jpg", "61.jpg", "62.jpg",
"63.jpg", "64.jpg", "65.jpg", "66.jpg"};
for(final String imageResource : imageResources) {
imageView = new ImageView(imageResource);
imageView.setFitWidth(50);
imageView.setFitHeight(26);
tiles.add(imageView);
}
//Assign mouse press handler.
for (ImageView imageView :
tiles) {
imageView.setOnMousePressed(this::onPress);
}
Collections.shuffle(tiles);
for (int i = 0; i < 7; i++) {
GridPane.setHalignment(tiles.get(0), HPos.CENTER);
humanHand.add(tiles.remove(0), i, 0);
}
humanHand.setOnMousePressed(event -> {
System.out.printf("Index to be removed %d \n", column);
humanHand.getChildren().remove(column);
});
humanHand.setAlignment(Pos.BOTTOM_CENTER);
AnchorPane.setBottomAnchor(humanHand, 25.0);
AnchorPane.setLeftAnchor(humanHand, 0.0);
AnchorPane.setRightAnchor(humanHand, 0.0);
root.getChildren().addAll(humanHand);
primaryStage.setScene(new Scene(root, 800, 350));
primaryStage.show();
}
//Handler for mouse press event.
private void onPress(MouseEvent event) {
column = GridPane.getColumnIndex((Node) event.getSource());
int row = GridPane.getRowIndex((Node) event.getSource());
System.out.printf("Node clicked at: column=%d, row=%d \n", column, row);
System.out.println(humanHand.getChildren().get(column));
}
}
Any help would be appreciated.
Just keep track of which ImageView is clicked on, instead of which column:
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DominoMain extends Application {
GridPane humanHand = new GridPane();
private ImageView clickedImage ;
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane root = new AnchorPane();
List<ImageView> tiles = new ArrayList<>();
String[] imageResources = new String[] {
"00.jpg", "10.jpg", "11.jpg", "20.jpg", "21.jpg", "22.jpg",
"30.jpg", "31.jpg", "32.jpg", "33.jpg", "40.jpg", "41.jpg",
"42.jpg", "43.jpg", "44.jpg", "50.jpg", "51.jpg", "52.jpg",
"53.jpg", "54.jpg", "55.jpg", "60.jpg", "61.jpg", "62.jpg",
"63.jpg", "64.jpg", "65.jpg", "66.jpg"};
for(final String imageResource : imageResources) {
ImageView imageView = new ImageView(imageResource);
imageView.setFitWidth(50);
imageView.setFitHeight(26);
tiles.add(imageView);
}
//Assign mouse press handler.
for (ImageView imageView :
tiles) {
imageView.setOnMousePressed(e -> clickedImage = imageView);
}
Collections.shuffle(tiles);
for (int i = 0; i < 7; i++) {
GridPane.setHalignment(tiles.get(0), HPos.CENTER);
humanHand.add(tiles.remove(0), i, 0);
}
humanHand.setOnMousePressed(event -> {
if (clickedImage != null) {
humanHand.getChildren().remove(clickedImage);
}
});
humanHand.setAlignment(Pos.BOTTOM_CENTER);
AnchorPane.setBottomAnchor(humanHand, 25.0);
AnchorPane.setLeftAnchor(humanHand, 0.0);
AnchorPane.setRightAnchor(humanHand, 0.0);
root.getChildren().addAll(humanHand);
primaryStage.setScene(new Scene(root, 800, 350));
primaryStage.show();
}
}

JavaFX, text won't display in TextArea

I have the majority of the program done, the only problem is getting the numbers to display in the TextArea. Write a program that lets the user enter numbers from a graphical user interface and displays them in a text area. Use a LinkedList to store the numbers. Don't duplicate numbers. Add sort, shuffle, reverse to sort the list.
package storedInLinkedList;
import java.util.Collections;
import java.util.LinkedList;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.ScrollPane;
public class StoredInLinkedList extends Application{
TextField txt = new TextField();
TextArea tArea = new TextArea();
Label message = new Label("Enter a Number: ");
Button sort = new Button("Sort");
Button shuffle = new Button("Shuffle");
Button reverse = new Button("Reverse");
private LinkedList<Integer> list = new LinkedList<>();
#Override
public void start(Stage primaryStage){
BorderPane bPane = new BorderPane();
txt.setAlignment(Pos.TOP_RIGHT);
bPane.setCenter(txt);
bPane.setBottom(tArea);
HBox hBox = new HBox(message, txt);
bPane.setTop(hBox);
HBox buttons = new HBox(10);
buttons.getChildren().addAll(sort, shuffle, reverse);
bPane.setBottom(buttons);
buttons.setAlignment(Pos.CENTER);
VBox vBox = new VBox();
vBox.getChildren().addAll(hBox, tArea, buttons);
bPane.setCenter(new ScrollPane(tArea));
Scene scene = new Scene(vBox, 300,250);
primaryStage.setTitle("20.2_DSemmes");
primaryStage.setScene(scene);
primaryStage.show();
txt.setOnAction(e -> {
if(! list.contains(new Integer(txt.getText()))){
tArea.appendText(txt.getText() + " ");
list.add(new Integer(txt.getText()));
}//end if
});//end action
sort.setOnAction(e -> {
Collections.sort(list);
display();
});//end action
shuffle.setOnAction(e -> {
Collections.shuffle(list);
display();
});//end action
reverse.setOnAction(e -> {
Collections.reverse(list);
display();
});//end action
}//end stage
private void display() {
for (Integer i: list){
tArea.setText(null);
tArea.appendText(i + " ");
}//end for
}//end display
public static void main(String[] args) {
// TODO Auto-generated method stub
launch(args);
}//end main
}//end class
Put the textarea clearing code outside of for loop. Otherwise you are clearing the previously appended text, so textarea having only the last element of list:
private void display() {
tArea.setText(""); // clear text area
for (Integer i: list){
tArea.appendText(i + " ");
}//end for
}/

Refresh label in JAVAFX

So i have this code in which i'm trying to do a scene for my game. I'm really a beginner in a Java and especially JAVAFX world and doing this as a school project (Once again..) and trying to figure out a way to refresh my label.
I've found one URL from stackoverflow, which was a similar issue but didn't work for my problem (or was i too stupid to make it work..) anyways, link is here
This is the part where the problem occurs - i have a text box, from which you have to enter player names. Every time a user inputs player name the label shows how many names have been entered, according to the nimedlist.size() which holds the names inside.
Label mängijate_arv = new Label("Mängijaid on sisestatud: "+nimedlist.size());
// if we press enter, program will read the name
nimiTekst.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.ENTER) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
}
}
}
});
startBox.getChildren().addAll(sisestus_mängijad, nimiTekst, mängijate_arv,
startButton2);
This is the whole code:
package application;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class Baila2 extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(final Stage peaLava) {
final Group root = new Group();
final BorderPane piir = new BorderPane();
piir.setPrefSize(960, 540);
final Text tekst = new Text();
tekst.setText("JOOMISMÄNG");
tekst.setFont(Font.font("Verdana", 40));
VBox nupudAlam = new VBox();
Button startButton = new Button("Start");
nupudAlam.setSpacing(20);
Button reeglidButton = new Button("Reeglid");
nupudAlam.setAlignment(Pos.CENTER);
startButton.setId("btn3");
startButton.setMaxWidth(160);
reeglidButton.setMaxWidth(160);
reeglidButton.setId("btn3");
nupudAlam.getChildren().addAll(startButton, reeglidButton);
piir.setTop(tekst);
piir.setAlignment(tekst, Pos.CENTER);
piir.setCenter(nupudAlam);
root.getChildren().add(piir);
// START NUPP TÖÖ
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(final ActionEvent event) {
final ArrayList nimedlist = new ArrayList();
piir.setVisible(false);
final BorderPane startPiir = new BorderPane();
final VBox startBox = new VBox();
Button startButton2 = new Button("ALUSTA!");
startButton2.setId("btn2");
startButton2.setMaxWidth(160);
startPiir.setPrefSize(960, 540);
final Text startTekst = new Text();
startTekst.setText("JOOMISMÄNG");
startTekst.setFont(Font.font("Verdana", 40));
startPiir.setTop(startTekst);
startPiir.setAlignment(startTekst, Pos.CENTER);
final TextField nimiTekst = new TextField();
nimiTekst.setText(null);
nimiTekst.setMaxWidth(250);
Label sisestus_mängijad = new Label(
"Sisesta 3-9 mängija nimed:");
sisestus_mängijad.setFont(Font.font("Verdana", 30));
sisestus_mängijad.setTextFill(Color.ORANGE);
Label mängijate_arv = new Label("Mängijaid on sisestatud: "+nimedlist.size());
// kui vajutatakse ENTER,siis loeme nime
nimiTekst.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.ENTER) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
}
}
}
});
startBox.getChildren().addAll(sisestus_mängijad, nimiTekst, mängijate_arv,
startButton2);
startBox.setSpacing(20);
startBox.setAlignment(Pos.CENTER);
startPiir.setCenter(startBox);
root.getChildren().add(startPiir);
}
});
// aknasündmuse lisamine
peaLava.setOnHiding(new EventHandler<WindowEvent>() {
public void handle(WindowEvent event) {
// luuakse teine lava
final Stage kusimus = new Stage();
// küsimuse ja kahe nupu loomine
Label label = new Label("Kas tõesti tahad kinni panna?");
Button okButton = new Button("Jah");
Button cancelButton = new Button("Ei");
// sündmuse lisamine nupule Jah
okButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
kusimus.hide();
}
});
// sündmuse lisamine nupule Ei
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
peaLava.show();
kusimus.hide();
}
});
// nuppude grupeerimine
FlowPane pane = new FlowPane(10, 10);
pane.setAlignment(Pos.CENTER);
pane.getChildren().addAll(okButton, cancelButton);
// küsimuse ja nuppude gruppi paigutamine
VBox vBox = new VBox(10);
vBox.setAlignment(Pos.CENTER);
vBox.getChildren().addAll(label, pane);
// stseeni loomine ja näitamine
Scene stseen2 = new Scene(vBox);
kusimus.setScene(stseen2);
kusimus.show();
}
}); // siin lõpeb aknasündmuse kirjeldus
// stseeni loomine ja näitamine
Scene stseen1 = new Scene(root, 960, 540, Color.GREEN);
peaLava.setTitle("BAILA 2.0");
// peaLava.setResizable(false);
stseen1.getStylesheets().add(
getClass().getClassLoader().getResource("test.css")
.toExternalForm());
peaLava.setScene(stseen1);
peaLava.show();
}
}
Sorry about Estonian language, it's compulsory in our school to write in our native language..
You can just do
nimiTekst.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.ENTER) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
mängijate_arv.setText("Mängijaid on sisestatud: "+nimedlist.size());
}
}
}
});
If you are not using Java 8 (you appear not to be, since you are implementing all the handlers the old, long way...), you will have to declare mängijate_arv as final:
final Label mängijate_arv = new Label("Mängijaid on sisestatud: "+nimedlist.size());
If you want to be extra cool with this, you can use bindings instead. You will have to make nimidlist an observable list:
final ObservableList<String> nimedlist = FXCollections.observableArrayList();
and then:
mängijate_arv.bind(Bindings.format("Mängijaid on sisestatud: %d", Bindings.size(nimedList)));
and don't put the mängijate_arv.setText(...) call in the handler. This solution is nicer in many ways, as if you remove items from the list (or add other items elsewhere in your code), then the label will still remain properly updated without any additional code.
One other thing: it's a bit better to use an action handler on the text field, instead of a low-level key event handler:
nimiTekst.setOnAction(new EventHandler<ActionEvent>() {
public void handle(final ActionEvent keyEvent) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
mängijate_arv.setText("Mängijaid on sisestatud: "+nimedlist.size());
}
}
});
(Sorry if I mangled your variable names. My Estonian is a bit weak ;). Your school's policy is a good one, for what it's worth.)

Drawing lines between Shapes laid out in HBox and VBox

I have a circle inside various containers (ScrollPane, Group, HBox and VBox)
I want to draw a line from 0,0 to the centre of the circle.
I think the code below shows the problem. There is some function unknown to me which should go
in //SOME CODE HERE TO WORK OUT WHERE THE CIRCLE IS to make it work
I have a sample application I wrote to simplify my problem.
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class TestAppForCoords extends Application {
//Scene Graph:
//ScrollPane - scroll
// - Group - root
// - HBox - hbox - with random padding
// - VBox
// - VBox - vbox - with random padding
// - Circle - circle
// - VBox
// - Group - lines
// - Line - line
#Override
public void start(final Stage primaryStage) throws Exception {
Random rand = new Random();
int randomNum1 = rand.nextInt((100 - 0) + 1) + 0;
int randomNum2 = rand.nextInt((100 - 0) + 1) + 0;
System.out.println(randomNum1);
System.out.println(randomNum2);
ScrollPane scroll = new ScrollPane();
scroll.setPrefSize(500, 300);
Scene scene = new Scene(scroll);
primaryStage.setScene(scene);
Group root = new Group();
HBox hbox = new HBox();
hbox.setPadding(new Insets(randomNum1));
VBox vbox = new VBox();
hbox.getChildren().add(new VBox());
vbox.setPadding(new Insets(randomNum2));
hbox.getChildren().add(vbox);
hbox.getChildren().add(new VBox());
Circle circle = new Circle();
circle.setRadius(10);
vbox.getChildren().add(circle);
Group lines = new Group();
root.getChildren().add(hbox);
root.getChildren().add(lines);
root.autosize();
Line line = new Line();
line.setStartX(0);
line.setStartY(0);
//SOME CODE HERE TO WORK OUT WHERE THE CIRCLE IS
line.setEndX(123);
line.setEndY(123);
lines.getChildren().add(line);
scroll.setContent(root);
primaryStage.show();
}
public static void main(String[] args) {
System.out.println("Start JavaFXTestApp");
launch(args);
System.out.println("End JavaFXTestApp");
}
}
Finally I have it working. I can add a setOnShown handler which is called to correct the line.
So I have found out that localToScene and sceneToLocal only work after the window is being displayed
primaryStage.setOnShown(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent arg0) {
Point2D p = circle.localToScene(circle.getCenterX(),circle.getCenterY());
p = line.sceneToLocal(p);
line.setEndX(p.getX());
line.setEndY(p.getY());
}
});
So the final working program is:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class TestAppForCoords extends Application {
//Scene Graph:
//ScrollPane - scroll
// - Group - root
// - VBox - vboxEXTRA - with random padding
// - HBox - hbox - with random padding
// - VBox
// - VBox - vbox - with random padding
// - Circle - circle
// - VBox
// - Group - lines
// - Line - line
Line line = new Line();
Circle circle = new Circle();
#Override
public void start(final Stage primaryStage) throws Exception {
Random rand = new Random();
int randomNum1 = rand.nextInt((100 - 0) + 1) + 0;
int randomNum2 = rand.nextInt((100 - 0) + 1) + 0;
int randomNum3 = rand.nextInt((100 - 0) + 1) + 0;
System.out.println(randomNum1);
System.out.println(randomNum2);
System.out.println(randomNum3);
ScrollPane scroll = new ScrollPane();
scroll.setPrefSize(500, 300);
Scene scene = new Scene(scroll);
primaryStage.setScene(scene);
Group root = new Group();
HBox hbox = new HBox();
hbox.setPadding(new Insets(randomNum1));
VBox vbox = new VBox();
hbox.getChildren().add(new VBox());
vbox.setPadding(new Insets(randomNum2));
hbox.getChildren().add(vbox);
hbox.getChildren().add(new VBox());
circle.setRadius(10);
vbox.getChildren().add(circle);
Group lines = new Group();
root.getChildren().add(hbox);
root.getChildren().add(lines);
root.autosize();
root.requestLayout();
lines.getChildren().add(line);
VBox vboxEXTRA = new VBox();
vboxEXTRA.setPadding(new Insets(randomNum3));
vboxEXTRA.getChildren().add(root);
scroll.setContent(vboxEXTRA);
line.setStartX(0);
line.setStartY(0);
//This dosen't work prob because we aren't drawing yet
Point2D p = circle.localToScene(circle.getCenterX(),circle.getCenterY());
p = line.sceneToLocal(p);
line.setEndX(p.getX());
line.setEndY(p.getY());
primaryStage.setOnShown(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent arg0) {
Point2D p = circle.localToScene(circle.getCenterX(),circle.getCenterY());
p = line.sceneToLocal(p);
line.setEndX(p.getX());
line.setEndY(p.getY());
}
});
primaryStage.show();
}
public static void main(String[] args) {
System.out.println("Start JavaFXTestApp");
launch(args);
System.out.println("End JavaFXTestApp");
}
}

Take a snapshot part of canvas in javaFX

I need to save some part of canvas to image that is from x1 > 0 and y1 > 0 to some x2 > x1 and y2 > y1. What I understand from javaFX API, snapshot must occupy a whole area of node, like
wim = new WritableImage(((int) width), ((int) height));
bufferedImage = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_ARGB);
parameter = new SnapshotParameters();
parameter.setTransform(new Translate(0, 200));
and then
node.snapshot(parameter, wim);
image = SwingFXUtils.fromFXImage(wim, bufferedImage);
Graphics2D gd = (Graphics2D) image.getGraphics();
gd.translate(0,200);
ImageIO.write(image, "png", file);
Hej Mohammad,
i made a small example for you with hard coded width and height for the WritableImage, maybe this will help you. I put a ChartBar on the Stage and take a snapshot of it, when the button is clicked.
package de.professional_webworkx.blog.takesnapshoot;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
/**
*
* #author Patrick Ott <Patrick.Ott#professional-webworkx.de>
*/
public class TakeSnapShoot extends Application {
#Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
Scene scene = new Scene(root, 1024, 768);
ObservableList<String> observableArrayList = FXCollections.observableArrayList();
observableArrayList.add("Kitchen");
observableArrayList.add("Living Room");
CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis();
final BarChart barChart = new BarChart(xAxis, yAxis);
xAxis.setLabel("Room");
XYChart.Series series = new XYChart.Series();
series.getData().add(new XYChart.Data<String, Number>("Kitchen", 1245));
series.getData().add(new XYChart.Data<String, Number>("Living Room", 245));
series.getData().add(new XYChart.Data<String, Number>("Child 1", 3445));
barChart.getData().add(series);
root.getChildren().add(barChart);
Button snapShotBtn = new Button("Take a Snapshot");
root.getChildren().add(snapShotBtn);
snapShotBtn.setOnAction((ActionEvent t) -> {
try {
SnapshotParameters parameters = new SnapshotParameters();
WritableImage wi = new WritableImage(100, 100);
WritableImage snapshot = barChart.snapshot(new SnapshotParameters(), wi);
File output = new File("snapshot" + new Date().getTime() + ".png");
ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", output);
} catch (IOException ex) {
Logger.getLogger(TakeSnapShoot.class.getName()).log(Level.SEVERE, null, ex);
}
});
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Patrick

Resources