How do you add to an existing scene in javafx? - java

I would like to add more javafx objects to my scene but i am not sure how. I have tried looking it up but i could not find anything.
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Main.fxml"));
Scene scene = new Scene(root,600,400);
// how would i add something here or further on?
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.setTitle("Test");
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
For example how would i add a polygon to this?

You don't add them to scene, but to root, the Parent node of the scene. You have to change Parent to whatever type of node you're using in the FXML file. The default in netbeans is AnchorPane so that's what I used.
public void start(Stage primaryStage) throws Exception {
try {
AnchorPane root = FXMLLoader.load(getClass().getResource("fxml/Main.fxml"));
Scene scene = new Scene(root, 600, 400);
//how would i add something here or further on?
root.getChildren().add(new Polygon(10,20,30,10,20,30));
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.setTitle("Test");
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
// don't leave me hanging bro!
Platform.exit();
}
}

I would recommend a different approach entirely. If you are using the NetBeans IDE, you can download a tool called SceneBuilder. This application lets you build and edit simple or complex JavaFX applications.
As your application becomes more and more complex, it makes more sense to use a tool like SceneBuilder. I used SceneBuilder to create a fairly complex client GUI in less than an hour. Life in JavaFX is easier with NetBeans and SceneBuilder (and I'm a guy who prefers Eclipse!)

Related

JDK doesn't see application and other classes

The imports are there, but compiler says Application, FXMLLoader don't exist. I have configured for JRE and JDK 11, using Eclipse with JavaFX extension.
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane) FXMLLoader.load(getClass().getResource("Apps.fxml"));
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
As Fabian already said in his comment, starting with JDK11 JavaFX is not included in the JDK anymore. You can download a separate SDK for JavaFX here: http://jdk.java.net/openjfx/

NotificationPane doesn't show up in Scene

I would like to display a NotificationPane after certain user actions. My application has multiple scenes and the NotificationPane should be showed up in the currently active scene.
The whole thing works with Notification, it pops up when I need it.
But I can't figure out how to make this work for NotificationPane.
Steps I made so far:
I tryed to put NotificationPane directly to my scene and call
show() - it works.
Now the Idea is to get the current pane by calling
stage.getScene().getRoot(), wrap it to NotificationPane and then call
show() - it doesn't work and I have no idea why.
((BorderPane) pane).setCenter(new Label("TEST")); this line is replacing buttons with text label, so stage.getScene().getRoot() is returning the right object
I made a simple program to test the behaviour. One button to call NotificationPane.
Any suggestions?
Here is my test program:
package application;
import org.controlsfx.control.NotificationPane;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button notificationPaneButton = new Button("NotificationPane");
notificationPaneButton.setOnAction(e -> showNotificationPane(primaryStage, "Notification text"));
VBox vbox = new VBox(5);
vbox.setAlignment(Pos.CENTER);
vbox.getChildren().addAll(notificationPaneButton);
BorderPane borderPane = new BorderPane();
borderPane.setCenter(vbox);
primaryStage.setTitle("Notifications test");
primaryStage.setScene(new Scene(borderPane, 300, 200));
primaryStage.show();
}
public void showNotificationPane(Stage stage, String message) {
Parent pane = stage.getScene().getRoot();
// ((BorderPane) pane).setCenter(new Label("TEST"));
NotificationPane notificationPane = new NotificationPane(pane);
notificationPane.setText(message);
if (notificationPane.showingProperty().get()) {
notificationPane.hide();
System.err.println("hide");
} else {
notificationPane.show();
System.err.println("show");
}
}
}
Ok, I see the problem now. Wrapping current pane is not enough, I also have to add the NotificationPane to the scene. Right?
Anyway my current solution is following:
get current scene
get current pane
wrap pane
replace current scene with the new one
To avoid wrapping NotificationPane multiple times I check if current pane is already a NotificationPane and then call show().
public void showNotificationPane(Stage stage) {
Scene scene = stage.getScene();
Parent pane = scene.getRoot();
if (!(pane instanceof NotificationPane)){
NotificationPane notificationPane = new NotificationPane(pane);
scene = new Scene(notificationPane, scene.getWidth(), scene.getHeight());
stage.setScene(scene);
notificationPane.show();
} else {
((NotificationPane)pane).show();
}
}

Trouble having javafx GUI background stay centered when resizing frame

So this is the code i have that launches the GUI i read on a previous post that it maybe has to do with the fact that my root is of type Group but i wasn't able to figure out how to implement any other way. The content inside the GUI gets eaten up when i try to resize the main frame manually.I want it to stay center and resize with the frame.
package view;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import singleton.MainModel;
public class MainView extends Application {
#Override
public void start(Stage primaryStage) {
// Initialize mainController.
MainController mainController = new MainController();
// Add the controller to the singleton.
MainModel.getModel().getMainData().setMainController(mainController);
// Initialize display components.
Group root = new Group();
Scene scene = new Scene(root, 1280, 720);
// Add mainController.
root.getChildren().addAll(mainController);
// Pin the root to scene and display it.
primaryStage.setScene(scene);
primaryStage.show();
// Properly terminate the application if the user presses the "X" window button.
primaryStage.setOnCloseRequest(event -> {
mainController.closeApplication();
stop();
});
// Set the title and make the application a fixed size.
primaryStage.setTitle("Visual Earth Modelling System");
primaryStage.setResizable(true);
primaryStage.sizeToScene();
// Add the stage to the singleton.
MainModel.getModel().getMainData().setMainStage(primaryStage);
// Go to the first screen.
mainController.goToLoginScreen();
}
/**
* To destroy resources upon application close. Should be called in all instances of a properly closed JavaFX application.
*/
#Override
public void stop() {
if (MainModel.getModel().getNetworkData().isHandlerSet())
MainModel.getModel().getNetworkData().closeHandler();
}
/**
* This method is actually not used in a correctly deployed JavaFX application. Instead, the start method above is called. This main serves as a fallback in case of improper configuration.
*/
public static void main(String[] args) {
launch(args);
}
}
Replace Group with StackPane. StackPane by default sets alignment of children to center. Just to be sure that alignment is correct you can set it explicity by StackPane.setAlignment(Pos value).
StackPane root = new StackPane();
root.setAlignment(Pos.CENTER);
root.getChildren().add(mainController);
Scene scene = new Scene(root, 1280, 720);

Application with BorderPane doesn't display simple button

very new to JavaFX I'm following a simple tutorial here
I created a new JavaFX project but it has a BorderPane as a default rather than a StackPane as the tutorial says, so I left it there.
The application only has a button on it and if I use the BorderPane the button isn't displayed.
If I change it to StackPane the button shows up.
Thinking that for some reason the BorderPane was clipping something off, I made the application windows full size, but I still couldn't see the button.
Here is the code with the BorderPane the one that doesn't display the button:
package application;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("This is a test!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
root.getChildren().add(btn);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Any idea?
Take a look at the docs about BorderPane:
BorderPane lays out children in top, left, right, bottom, and center
positions.
Therefore you need to use stuff like:
borderPane.setTop(toolbar);
borderPane.setCenter(appContent);
borderPane.setBottom(statusbar);
In your case root.getChildren().add(btn); should be for example root.setCenter(btn);.

Change Scene without resize window in JavaFX

I'm trying to change Scenes on JavaFX, but without change the window size. However, when I set stage.setScene(scene2); the window size decreases, and I want to keep the both Scenes maximized. I've tried to stage.setMaximized(true) after the stage.setScene(scene2); but the result is the same.
How can I fix it?
My code:
package controller;
import java.io.IOException;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.util.Duration;
public class App extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("../view/fxml/Loading.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Project");
stage.setMaximized(true);
stage.show();
FadeTransition fadeIn = new FadeTransition(Duration.seconds(1), root);
fadeIn.setFromValue(0);
fadeIn.setToValue(1);
FadeTransition fadeOut = new FadeTransition(Duration.seconds(1), root);
fadeOut.setFromValue(1);
fadeOut.setToValue(0);
fadeIn.play();
fadeIn.setOnFinished((e) -> {
fadeOut.play();
});
fadeOut.setOnFinished((e) -> {
try {
Parent root2 = FXMLLoader.load(getClass().getResource("../view/fxml/Welcome.fxml"));
Scene scene2 = new Scene(root2);
stage.setScene(scene2);
} catch (IOException e1) {
e1.printStackTrace();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
When I compile:
Then the fadeOut/fadeIn occurs and (It is here that I want to keep maximized):
It's probably better here just to replace the root of the existing scene, than to create a new scene:
fadeOut.setOnFinished((e) -> {
try {
Parent root2 = FXMLLoader.load(getClass().getResource("../view/fxml/Welcome.fxml"));
scene.setRoot(root2);
} catch (IOException e1) {
e1.printStackTrace();
}
});
If you really do need to replace the scene, for some reason, you can set the new scene's size to the same as the existing scene:
fadeOut.setOnFinished((e) -> {
try {
Parent root2 = FXMLLoader.load(getClass().getResource("../view/fxml/Welcome.fxml"));
Scene scene2 = new Scene(root2, scene.getWidth(), scene.getHeight());
stage.setScene(scene2);
} catch (IOException e1) {
e1.printStackTrace();
}
});
I have been dealing with an issue similar to yours for the last 4-5 hours and given #James_D's answer I saw the way to simply fix the resizing issue with scene changes. This answer still directly goes off of #James_D, but I did not feel there was a clear explanation as to what was going on, so more than anything I am posting this to help anybody who runs across this thread understand why the second solution #James_D provided (i.e. Changing scenes, not the root of the scene) works.
Note: I did run across a few answers stating that setting a new root for the scene may be a better option than changing the whole scene, but that did not work in my case, so changing scenes was the best option for me.
Anyways, I am pretty sure the reason the scene changes sizes when swapped is because you do not set the scene width and height attributes on the scene object explicitly. Not specifically setting the size appears to make the scene adjust to the bounds of the objects it contains automatically when the new scene is loaded to the stage.
Basically, to fix the problem all you need to do is set the width and height attributes when you create your scene, like below.
Before
Scene scene2 = new Scene(root2);
After
Scene scene2 = new Scene(root2, 900, 600);//or whatever size you want
stage.setScene(scene2);//now we are set if initial scene is 900w X 600h, scene size will stay the same

Categories