Take a snapshot part of canvas in javaFX - 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

Related

why does while() loop not work on pathTransition?

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();
}
}

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 8 scale node for printing without changing displayed node

In JavaFX 8, I am printing a node (e.g., ScatterChart) with printerJob.printPage(). Without scaling, the printed node is cropped. If I scale for printing, then the printed node is correctly fit to the page, but the displayed node is scaled. A simple solution would be to make a copy/clone of the node, but it appears that isn't supported. Is there a better solution than scaling the node and then removing the scaling (which causes the displayed node to briefly rescale, which is unsightly)? It would seem that printing a graph would be a basic operation for JavaFX.
You can play with this app. It creates a PNG of the chart. It then prints the chart. I didn't scale the image. The actual image is located in your source folder. You can also open it using Paint and print from there. You can also code the printer settings so that the printer dialog shows up before printing.
import java.awt.Graphics;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import static java.awt.print.Printable.NO_SUCH_PAGE;
import static java.awt.print.Printable.PAGE_EXISTS;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
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.Image;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
/**
*
* #author blj0011
*/
public class JavaFXApplication145 extends Application
{
final static String itemA = "A";
final static String itemB = "B";
final static String itemC = "F";
#Override
public void start(Stage stage) {
final NumberAxis xAxis = new NumberAxis();
final CategoryAxis yAxis = new CategoryAxis();
final BarChart<Number, String> bc = new BarChart<Number, String>(xAxis, yAxis);
bc.setTitle("Summary");
xAxis.setLabel("Value");
xAxis.setTickLabelRotation(90);
yAxis.setLabel("Item");
XYChart.Series series1 = new XYChart.Series();
series1.setName("2003");
series1.getData().add(new XYChart.Data(2, itemA));
series1.getData().add(new XYChart.Data(20, itemB));
series1.getData().add(new XYChart.Data(10, itemC));
XYChart.Series series2 = new XYChart.Series();
series2.setName("2004");
series2.getData().add(new XYChart.Data(50, itemA));
series2.getData().add(new XYChart.Data(41, itemB));
series2.getData().add(new XYChart.Data(45, itemC));
XYChart.Series series3 = new XYChart.Series();
series3.setName("2005");
series3.getData().add(new XYChart.Data(45, itemA));
series3.getData().add(new XYChart.Data(44, itemB));
series3.getData().add(new XYChart.Data(18, itemC));
Button button = new Button("Print Chart");
button.setOnAction((event)->{printImage(saveAsPng(bc));});//Create the image and print it.
VBox vbox = new VBox();
vbox.getChildren().add(bc);
StackPane stackPane = new StackPane();
stackPane.getChildren().add(button);
vbox.getChildren().add(stackPane);
Scene scene = new Scene(vbox, 800, 600);
bc.getData().addAll(series1, series2, series3);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
public File saveAsPng(BarChart barChart) {
WritableImage image = barChart.snapshot(new SnapshotParameters(), null);
// TODO: probably use a file chooser here
File file = new File("chart.png");
try {
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file);
} catch (IOException e) {
// TODO: handle exception here
}
return file;
}
private void printImage(File file) {
Image image = new Image(file.toURI().toString());
java.awt.image.BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable(new Printable() {
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
// Get the upper left corner that it printable
int x = (int) Math.ceil(pageFormat.getImageableX());
int y = (int) Math.ceil(pageFormat.getImageableY());
if (pageIndex != 0) {
return NO_SUCH_PAGE;
}
graphics.drawImage(bufferedImage, x, y, bufferedImage.getWidth(), bufferedImage.getHeight(), null);
return PAGE_EXISTS;
}
});
try {
printJob.print();
} catch (PrinterException e1) {
e1.printStackTrace();
}
}
}

JavaFX Change ScrollPane ViewPort background color

I need to change the gray background color of the ScrollPane so where you see WHITE and BOLD Labels i want the background to be white.
Image from the Application.
Code:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class MainApp extends Application {
private static final int WINDOW_WIDTH = 800;
private static final int WINDOW_HEIGHT = 200;
private String family = "Helvetica";
private TextFlow textFlow = new TextFlow();
#Override
public void start(Stage stage) {
HBox hbox = new HBox();
Group group = getGroup();
hbox.getChildren().add(group);
hbox.setAlignment(Pos.TOP_LEFT);
hbox.getStyleClass().add("hbox");
MenuBar menuBar = new MenuBar();
menuBar.prefWidthProperty().bind(stage.widthProperty());
// File menu - new, save, exit
Menu fileMenu = new Menu("File");
MenuItem newMenuItem = new MenuItem("New");
MenuItem saveMenuItem = new MenuItem("Save");
MenuItem exitMenuItem = new MenuItem("Exit");
exitMenuItem.setOnAction(actionEvent -> Platform.exit());
fileMenu.getItems().addAll(newMenuItem, saveMenuItem,
new SeparatorMenuItem(), exitMenuItem);
Menu webMenu = new Menu("Web");
CheckMenuItem htmlMenuItem = new CheckMenuItem("HTML");
htmlMenuItem.setSelected(true);
webMenu.getItems().add(htmlMenuItem);
CheckMenuItem cssMenuItem = new CheckMenuItem("CSS");
cssMenuItem.setSelected(true);
webMenu.getItems().add(cssMenuItem);
Menu sqlMenu = new Menu("SQL");
ToggleGroup tGroup = new ToggleGroup();
RadioMenuItem mysqlItem = new RadioMenuItem("MySQL");
mysqlItem.setToggleGroup(tGroup);
RadioMenuItem oracleItem = new RadioMenuItem("Oracle");
oracleItem.setToggleGroup(tGroup);
oracleItem.setSelected(true);
sqlMenu.getItems().addAll(mysqlItem, oracleItem,
new SeparatorMenuItem());
Menu tutorialManu = new Menu("Tutorial");
tutorialManu.getItems().addAll(
new CheckMenuItem("Java"),
new CheckMenuItem("JavaFX"),
new CheckMenuItem("Swing"));
sqlMenu.getItems().add(tutorialManu);
menuBar.getMenus().addAll(fileMenu, webMenu, sqlMenu);
ScrollPane scrollPane = new ScrollPane(hbox);
scrollPane.setFitToHeight(true);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
BorderPane root = new BorderPane(scrollPane);
root.setPadding(new Insets(15));
root.setTop(menuBar);
//root.setCenter(hbox);
Scene scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
//scene.getStylesheets().add("layoutstyle.css");
stage.setTitle("Dummy Title");
stage.setScene(scene);
stage.show();
Text text3 = new Text("\nDummy text");
text3.setFont(Font.font(family, 22));
textFlow.getChildren().add(text3);
}
private Group getGroup(){
double size = 50;
textFlow = new TextFlow();
textFlow.setLayoutX(40);
textFlow.setLayoutY(40);
Text text1 = new Text("White");
text1.setFont(Font.font(family, size));
text1.setFill(Color.RED);
Text text2 = new Text("\nBold");
text2.setFill(Color.ORANGE);
text2.setFont(Font.font(family, FontWeight.BOLD, size));
Text text3 = new Text("\n World");
text3.setFill(Color.GREEN);
text3.setFont(Font.font(family, FontPosture.ITALIC, size));
textFlow.getChildren().addAll(text1, text2, text3);
return new Group(textFlow);
}
public static void main(String[] args) {
launch(args);
}
}
You have to modify the .viewport color of the ScrollPane with css:
CSS code:
/*The ViewPort of the ScrollPane */
.scroll-pane .viewport {
-fx-background-color: white; /*or whatever you want*/
}
.scroll-pane {
-fx-background-color:transparent;
}
And change these lines of code from your application:
//........
//.........
root.setPadding(new Insets(15));
root.setTop(menuBar);
//root.setCenter(hbox);
Scene scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
stage.setTitle("Dummy Title");
stage.setScene(scene);
stage.show();
//........
//.........
Finally mention that the css file which contains the css code,in this example has to be in the same source folder as the Application.java file.
I guess your question is, how to apply a white background?
via css-style (an entry in your css-File would be better for that):
root.setStyle("-fx-background-color:white");
menuBar.styleProperty().bind(root.styleProperty());
via api
Background background = new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY));
root.setBackground(background);
menuBar.setBackground(background);

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");
}
}

Resources