How to make scene local JavaFX - javafx

The scene at the start of lambda has an error that is not local. How to make it local. I tried adding up top but shows null. How to make scene local at the lambda because scene sets primaryStage. I need the other nodes for GridPane. I am trying to draw on the canvas. Please help fix this problem. Thank you in advanced!
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class TestFX extends Application {
Node scene; // i tried adding this but throws null at the lambda
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("MyPaint");
RadioButton radioButton1 = new RadioButton("Draw");
RadioButton radioButton2 = new RadioButton("Erase");
RadioButton radioButton3 = new RadioButton("Circle");
ToggleGroup radioGroup = new ToggleGroup();
radioButton1.setToggleGroup(radioGroup);
radioButton2.setToggleGroup(radioGroup);
radioButton3.setToggleGroup(radioGroup);
Button b1 = new Button("Clear Canvas");
TextField colorText = new TextField();
colorText.setText("Colors");
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
// scene cannot be resolved without initializing at top: Node scene;
scene.setOnMousePressed(q -> {
gc.setFill(Color.BLACK);
gc.setLineWidth(1);
gc.beginPath();
gc.lineTo(q.getSceneX(),
q.getSceneY());
gc.getStroke();
});
gc.strokeText("Hello Canvas", 150, 100);
GridPane gridPane = new GridPane();
GridPane.setConstraints(radioButton1, 0, 0);
GridPane.setConstraints(radioButton2, 0, 1);
GridPane.setConstraints(radioButton3, 0, 2);
GridPane.setConstraints(colorText, 0, 3);
GridPane.setConstraints(b1, 0, 4);
GridPane.setConstraints(canvas, 1, 1);
// adding spaces between radiobutton, button and radiobutton
radioButton1.setPadding(new Insets(15));
radioButton2.setPadding(new Insets(15));
radioButton3.setPadding(new Insets(15));
b1.setPadding(new Insets(15));
colorText.setPadding(new Insets(15));
gridPane.getChildren().addAll(radioButton1, radioButton2, radioButton3, colorText, b1, canvas);
Scene scene = new Scene(gridPane, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

You define Scene in this part of the code:
gridPane.getChildren().addAll(radioButton1, radioButton2, radioButton3, colorText, b1, canvas);
Scene scene = new Scene(gridPane, 800, 800);
primaryStage.setScene(scene);
primaryStage.show()
but you are calling this code before you define Scene.
// scene cannot be resolved without initializing at top: Node scene;
scene.setOnMousePressed(q -> {
gc.setFill(Color.BLACK);
gc.setLineWidth(1);
gc.beginPath();
gc.lineTo(q.getSceneX(),
q.getSceneY());
gc.getStroke();
});
You need to delete Node scene. and move the scene.setOnMousePressed() code to a place after where you defined the Scene.
Full Code:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class TestFX extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("MyPaint");
RadioButton radioButton1 = new RadioButton("Draw");
RadioButton radioButton2 = new RadioButton("Erase");
RadioButton radioButton3 = new RadioButton("Circle");
ToggleGroup radioGroup = new ToggleGroup();
radioButton1.setToggleGroup(radioGroup);
radioButton2.setToggleGroup(radioGroup);
radioButton3.setToggleGroup(radioGroup);
Button b1 = new Button("Clear Canvas");
TextField colorText = new TextField();
colorText.setText("Colors");
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.strokeText("Hello Canvas", 150, 100);
GridPane gridPane = new GridPane();
GridPane.setConstraints(radioButton1, 0, 0);
GridPane.setConstraints(radioButton2, 0, 1);
GridPane.setConstraints(radioButton3, 0, 2);
GridPane.setConstraints(colorText, 0, 3);
GridPane.setConstraints(b1, 0, 4);
GridPane.setConstraints(canvas, 1, 1);
// adding spaces between radiobutton, button and radiobutton
radioButton1.setPadding(new Insets(15));
radioButton2.setPadding(new Insets(15));
radioButton3.setPadding(new Insets(15));
b1.setPadding(new Insets(15));
colorText.setPadding(new Insets(15));
gridPane.getChildren().addAll(radioButton1, radioButton2, radioButton3, colorText, b1, canvas);
Scene scene = new Scene(gridPane, 800, 800);
scene.setOnMousePressed(q -> {
gc.setFill(Color.BLACK);
gc.setLineWidth(1);
gc.beginPath();
gc.lineTo(q.getSceneX(),
q.getSceneY());
gc.getStroke();
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

Exception in thread "JavaFX Application Thread" java.lang.illegalArgumentException: Grid hgap=10.0

my name is Omar, I made this code in javafx in order to switch between scene 0 and scene 1.
When an input scanner laser barcode number is introduced (6590055780)
it changes from scene 0 to scene 1, once in scene 1, if user pressed a button will change to scene 0.
But when i compile this code, it gives me the following error
"Exception in thread "JavaFX Application Thread" java.lang.illegalArgumentException: Grid hgap=10.0 alignment=CENTERis already set as root of another scene"
I do not know why i get this error, it is like the setOnKeyPressed does not allow me to leave from it, when i want to switch from scene 0 to scene 1, i got this error message, anyhelp is appreciated in order to solve this problem. thank you very much
and this is the code
import javafx.application.Application;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyEvent;
public class scannerinputfx2 extends Application {
////////////* public class*///////
public static String salida;
#Override
public void start(Stage primaryStage){
primaryStage.setTitle("what's up");
//scene 0
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Scene scene = new Scene(grid, 300, 275);
TextArea area = new TextArea();
TextField userTextField = new TextField();
//grid.add(userTextField, 0, 0);
//grid.add(area, 0,1);
GridPane.setConstraints(userTextField, 0,0);
GridPane.setConstraints(area,0,1);
grid.getChildren().addAll(area, userTextField);
//scene 1
GridPane grid1 = new GridPane();
grid1.setAlignment(Pos.CENTER);
grid1.setHgap(10);
grid1.setVgap(10);
grid1.setPadding(new Insets(25, 25, 25, 25));
Scene scene1 = new Scene(grid1, 300, 275);
Button btnfinal = new Button("Press button to get back");
GridPane.setConstraints(btnfinal, 0, 0);
grid1.getChildren().addAll(btnfinal);
btnfinal.setOnAction(actionEvent -> {
scene1.setRoot(grid);
});
primaryStage.setScene(scene);
primaryStage.show();
userTextField.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent ke) {
area.setText( userTextField.getText());
if (userTextField.getText().equals("6590055780"))
{
System.out.println("The number is " + userTextField.getText());
userTextField.setText("");
scene.setRoot(grid1);
}
else
{
System.out.println("The number is not the indicated");
}
}
});
}
////////*Here finish primary stage/////////
public static void main(String[] args) {
launch(args);
}
}

JavaFx Chat TextField and Button Key Listener

Im a beginner working on a simple Chat with javafx, i have already searched for similar problems and didnt find a fitting solution. The first thing i need to do is the Graphics. My first Problem is, that my MousEvent Listener for the Button isnt working, i simply cant click the Button somehow. My second problem is, once the application is running and i click somewhere outside of the TextField, i cant return to it and enter new Text. Like the Listeners of the TextField, which listen for KeyStroke events dont run anymore. Code:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ChatView extends Application {
String s;
#Override
public void start(Stage stage){
s = "";
StackPane rootPane = new StackPane();
TextField enterMessageField = new TextField();
enterMessageField.setEditable(true);
TextArea displayAllMessages = new TextArea();
displayAllMessages.setPrefHeight(500);
displayAllMessages.setEditable(false);
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(displayAllMessages);
scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS);
displayAllMessages.setPrefWidth(650);
Button button = new Button("Send Message");
VBox vBoxChat = new VBox();
vBoxChat.setPadding(new Insets(650, 200, 20, 20));
vBoxChat.getChildren().addAll( enterMessageField);
VBox vBoxChatIncoming = new VBox();
vBoxChatIncoming.setPadding(new Insets(20, 20, 20, 20));
vBoxChatIncoming.getChildren().addAll( scrollPane);
VBox vBoxEnter = new VBox();
vBoxEnter.setPadding(new Insets(650, 20, 20, 550));
vBoxEnter.getChildren().add(button);
rootPane.getChildren().addAll(vBoxChat, vBoxEnter, vBoxChatIncoming);
Scene scene = new Scene(rootPane, 700, 700, Color.WHITE);
stage.setScene(scene);
stage.setTitle("Chat");
stage.show();
enterMessageField.setOnKeyPressed(new EventHandler <KeyEvent> () {
#Override
public void handle(KeyEvent event){
if (event.getCode() == KeyCode.ENTER){
s = enterMessageField.getText() + "\n";
enterMessageField.setText("");
displayAllMessages.appendText(s);
}
}
});
button.setOnAction((event) -> {
s = enterMessageField.getText() + "\n";
enterMessageField.setText("");
System.out.println(s);
});
}
public static void main(String[] args){
launch(args);
}
}
Thank you for your help!
I changed the rootPane to GridPane and this fact fixed the problems.
Actually the StackPane is not suitable type for multicomponent interface. See the similar problem here: Mouse Events get Ignored on the Underlying Layer
See a bit improved code below:
public class ChatView extends Application {
String s = "";
#Override
public void start(Stage stage) {
TextField enterMessageField = new TextField();
enterMessageField.setEditable(true);
TextArea displayAllMessages = new TextArea();
displayAllMessages.setPrefHeight(500);
displayAllMessages.setEditable(false);
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(displayAllMessages);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
displayAllMessages.setPrefWidth(650);
Button button = new Button("Send Message");
button.setDefaultButton(true);
VBox vBoxChat = new VBox(enterMessageField);
vBoxChat.setPadding(new Insets(10, 10, 10, 10));
VBox vBoxChatIncoming = new VBox(displayAllMessages);
vBoxChatIncoming.setPadding(new Insets(10, 10, 10, 10));
VBox vBoxEnter = new VBox(button);
vBoxEnter.setPadding(new Insets(10, 10, 10, 10));
GridPane rootPane = new GridPane();
rootPane.add(vBoxChatIncoming, 0, 0);
rootPane.add(vBoxChat, 0, 1);
rootPane.add(vBoxEnter, 1, 1);
Scene scene = new Scene(rootPane, 800, 700, Color.WHITE);
stage.setScene(scene);
stage.setTitle("Chat");
stage.show();
enterMessageField.setOnKeyPressed(event -> {
if (event.getCode() == KeyCode.ENTER) {
s = enterMessageField.getText() + "\n";
enterMessageField.setText("");
displayAllMessages.appendText(s);
}
});
button.setOnAction((event) -> {
s = enterMessageField.getText() + "\n";
enterMessageField.setText("");
System.out.println(s);
});
}
public static void main(String[] args) {
launch(args);
}
}

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

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

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