How can I get objects from FXML to Java Code - javafx

I created a GridPane in my JFX Fluidon Designer and I'm trying to reference it in one of my java files.
More specifically, I'd like to programatically put it inside a Vbox with an Hbox I also created in Java. I'll post the code below, it might make more sense.
When I run this code, I get an error that my gridPane variable is null when I use it in the addAll method.
Thanks in advance!
public class MyProgram extends Application {
Label mStatus;
ImageView img_x;
ImageView img_o;
#FXML public GridPane gridPane;
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
img_x = new ImageView("file:x.png");
img_o = new ImageView("file:o.png");
img_x.setUserData("X");
img_o.setUserData("O");
HBox hbox = new HBox();
hbox.getChildren().addAll(img_x, img_o);
VBox vbox = new VBox();
vbox.getChildren().addAll(hbox, gridPane);
root.setCenter(vbox);

Related

Add JavaFX Label - (Using Only Java / JavaFX Code) - To Existing GUI Created With Scenebuilder / FXML

I Created a complete GUI using ONLY Scenebuilder FXML Techniques
Something Like This :-
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root=FXMLLoader.load(getClass().getResource("backupmenu.fxml"));
primaryStage.setTitle("Backup Affected Files And Folders Only");
primaryStage.setScene(new Scene( root, 800, 400));
primaryStage.show();
}
}
However I want to add a label to that SAME EXISTING GUI but this time using ONLY Java Code / JavaFX Label Techniques ?
I.E Using Traditional Methods such as this Example Below :-
// launch the application
public void start(Stage s)
{
// set title for the stage
s.setTitle("creating label");
// create a label
Label b = new Label("This is a label");
// create a Stack pane
StackPane rootpane = new StackPane();
// add password field
rootpane.getChildren().add(b);
// create a scene
Scene sc = new Scene(rootpane, 200, 200);
// set the scene
s.setScene(sc);
s.show();
}
public static void main(String args[])
{
// launch the application
launch(args);
}
}
I cannot find a web search result that even comes close to matching my very specific question .
Can i combine the 2 techniques - Is it Possible ?
Yes, this is possible.
You need a reference to the Parent (some kind of container Pane or Node) you want to add the Label to in your controller class.
For example, suppose your FXML defines a VBox with an id of "root":
<VBox fx:id="root">
In your controller, define a reference to that VBox:
#FXML
private VBox root;
Then you can add anything you want to the VBox:
root.getChildren().add(new Label("Hi, I'm a new Label!"));

How to make pane and elements in it resizable when stage size is changing

Can you please tell me how can I realize that the whole content of a pane will be resized while the stage is resized with mousedragg. Here is my code:
public class fab extends Application {
private Stage stage;
private Pane pane;
private Scene scene;
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
Button button = new Button("Button");
pane = new Pane();
pane.getChildren().add(button);
stage.setTitle("Test");
scene = new Scene(pane, 640, 640);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
I think there is the idea of binding. But I don't know how to use that, in order to make all nodes of a pane resizable, when the stage size is changing.
I'm searching a solution without Fxml or sceneBuilder.
Thank you in advance.
If you insists to use the Pane container then after the line scene = new Scene(pane, 640, 640); add this:
scene.widthProperty().addListener((c,o,n)->button.setPrefWidth((Double)n));
scene.heightProperty().addListener((c,o,n)->button.setPrefHeight((Double)n));
and after the line stage.setScene(scene); add this:
button.setPrefSize(scene.getWidth(), scene.getHeight());
This works fine with Pane and do your required thing.
But I prefer using an AnchorPane container and set the Top, Right,Bottom and Left anchors to 0 .
Here is the solution if you wish to bind the width of the button to you scene width
button.minWidthProperty().bind(scene.widthProperty());
You can also modify this +/- whatever you want for ex
button.minWidthProperty().bind(scene.widthProperty().subtract(20));
and you can do the same for the height
button.minHeightProperty().bind(scene.heightProperty().subtract(200));

JavaFX + Scene Builder how switch scene

I'm working with JavaFx and Scenebuilder and want create a local app for myself called "Taskplanner" in eclipse.
I created a new Stage and set it with a Scene (see Main.java). But not sure how to set a new Scene in the old stage (see Controller.java). Didnt also not find out if it is possible pass the signInButtonClicked()-Methode the "Stage primaryStage" over Scene Builder
Can anybody help ?
Controller.java:
#FXML
Button btnSignIn;
#FXML
public void signInButtonClicked() throws Exception
{
//Here I want call the new Scene(SignInGUI.fxml) in my old Stage
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../view/SignInGUI.fxml"));
}
Main.java:
#Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("../view/LoginGUI.fxml"));
primaryStage.setTitle("Taskplanner");
primaryStage.setScene(new Scene(root,500,500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
You can get a reference to the Scene and Window from your button reference. From there, it's up to you to decide how to you want to show the new view.
Here's how you get those references:
Scene scene = btnSignIn.getScene();
Window window = scene.getWindow();
Stage stage = (Stage) window;
You can change the view by changing the root of your Scene:
FXMLLoader loader = ... // create and load() view
btnSignIn.getScene().setRoot(loader.getRoot());
Or you can change the entire Scene:
FXMLLoader loader = ... // create and load() view
Stage stage = (Stage) btnSignIn.getScene().getWindow();
Scene scene = new Scene(loader.getRoot());
stage.setScene(scene);

How to get the size of a label before it is laid out?

I read this old answer on how to accomplish this. But since it involves using impl_processCSS(boolean), a method that is now deprecated, I think we need to update the answer.
I've tried placing the label inside a HBox and then get the size of it, or getting the size of the HBox, without any luck. And I've also tried using .label.getBoundsInLocal().getWidth().
SSCCE:
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.application.Application;
import javafx.scene.Scene;
public class SSCCE extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
HBox root = new HBox();
Label label = new Label("foo");
System.out.println(label.getWidth());
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Since JavaFX 8, the method you are looking for is applyCss().
As JavaDoc states:
apply styles to this Node and its children, if any. This method does not normally need to be invoked directly but may be used in conjunction with Parent.layout() to size a Node before the next pulse, or if the Scene is not in a Stage.
So you need to have the node in the container, and this one already on the scene, and also call layout().
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Label label = new Label("foo bla bla");
root.getChildren().add(label);
Scene scene = new Scene(root);
root.applyCss();
root.layout();
System.out.println(label.getWidth());
primaryStage.setScene(scene);
primaryStage.show();
}
Being the output: 17.818359375
Note I've changed HBox for Group, since:
a Group will "auto-size" its managed resizable children to their preferred sizes during the layout pass to ensure that Regions and Controls are sized properly as their state changes
If you use an HBox, you need to set also the dimensions of the scene:
#Override
public void start(Stage primaryStage) {
HBox root = new HBox();
Label label = new Label("foo");
root.getChildren().add(label);
Scene scene = new Scene(root,100,20);
root.applyCss();
root.layout();
System.out.println(label.getWidth());
primaryStage.setScene(scene);
primaryStage.show();
}
Now the output is: 18.0

Opening a new scene in java FX

I have two FXML files and one Controller.
I have posted the code in which i have tried to create a second stage (and failed).
Error message is:
javafx.scene.layout.AnchorPane cannot be cast to javafx.fxml.FXMLLoader
How do I fix it?
#FXML private Scene trial_scene;
#FXML public Stage m;
#FXML public void click(Stage stage) throws IOException {
m = new Stage();
openWindow();
}
#FXML private void openWindow() throws IOException {
FXMLLoader root =FXMLLoader.load(
SampleController.class.getResource(
"settings.fxml"
)
);
m.initModality(Modality.WINDOW_MODAL);
m.setTitle("My modal window");
m.setScene(trial_scene);
m.show();
}
The static method FXMLLoader.load returns the root node (and so the objet hierarchy) defined in the .fxml file. In your case it seems to be an AnchorPane.
Your fist line should be
AnchorPane root = FXMLLoader.load(SampleController.class.getResource("settings.fxml"));
Use this object to construct your new scene, for example
Scene trial_scene = new Scene(root, 300, 300, Color.BLACK);
Then pass this scene to your new stage
m.setScene(trial_scene);

Resources