I want to switch the scenes of my JavaFX application in Fullscreen with a "Next"-Button. But if I click on that Button it switches from fullscreen to windowed and back to fullscreen within a second. How can I achieve to avoid that and stay in fullscreen mode?
Some relevant snippets:
Application.java:
public class Application extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLMain.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
stage.setFullScreen(true);
stage.setTitle("AppName");
}
public static void main(String[] args) {
launch(args);
}
}
FXMLMainController.java:
#FXML
private void handleBtnNext(ActionEvent event) throws Exception{
Stage stage;
Parent root;
if(event.getSource()==btnNext){
//get reference to the button's stage
stage=(Stage) btnNext.getScene().getWindow();
//load up OTHER FXML document
root = FXMLLoader.load(getClass().getResource("FXMLOptions.fxml"));
}
else{
stage=(Stage) btnNext.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXMLMain.fxml"));
}
//create a new scene with root and set the stage
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
stage.setFullScreen(true);
}
That behavior, where the app pops out of full screen mode when you switch scenes, is weird (it happens for me too on Java 8u60, OS X 10.11.3). It may be a bug.
To work-around it, you can just reuse the same stage and scene and adjust the root of your scene, rather than changing the scene itself.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FullScreenScenes extends Application {
#Override
public void start(Stage stage) throws Exception {
Button next1 = new Button("Show Scene 2");
StackPane layout1 = new StackPane(next1);
layout1.setStyle("-fx-background-color: palegreen;");
Button next2 = new Button("Show Scene 1");
StackPane layout2 = new StackPane(next2);
layout2.setStyle("-fx-background-color: paleturquoise;");
Scene scene = new Scene(layout1);
next1.setOnAction(event -> scene.setRoot(layout2));
next2.setOnAction(event -> scene.setRoot(layout1));
stage.setScene(scene);
stage.setFullScreen(true);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
first Adjust your scene Builder view (Responsive responsive screen sizes) this is your Scene Builder View problem Adjust the view (Layout or Fxid ) check again .
Related
I currently have
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
String dd = "Hello";
stage.setTitle("Greetings"); //creates title
button_roll = new Button("Roll");
StackPane layout1 = new StackPane();
layout1.getChildren().add(button_roll);
Scene scene1 = new Scene(layout1, 600, 600);
stage.setScene(scene1);
Label mylab = new Label();
mylab.setText(dd);
Scene scene2 = new Scene(mylab, 600, 600);
button_roll.setOnAction(e -> stage.setScene(scene2));
stage.show();
}
My code currently displays "Hello" into the scene as a new scene.
I was wondering if there was a way to just update the scene1 to display the text instead of creating a whole new scene with just the text in it.
Is there terminology for what I want to do, if so what is it?
Any help would be great!
Your problem is you never add the Label to the Scene. Having the root node as StackPane will stack the Label and Button over each other. You need to replace StackPane with VBox, HBox, or a more suitable Node. Comments in the code.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application
{
#Override
public void start(Stage stage) throws Exception
{
String helloString = "Hello";//String use in the lable once the button is pressed.
Label lblHello = new Label();//Label that will show helloString once the button is pressed.
Button btnRoll = new Button("Roll");//The button that will trigger the action to change the label from empty string to helloString.
btnRoll.setOnAction((t) -> {//Set the button's action
lblHello.setText(helloString);//set the label's text to helloString.
});
VBox vbLayoutRoot = new VBox(lblHello, btnRoll);//The root layout is a VBox. Add the label and the btn to the root layout.
Scene scene = new Scene(vbLayoutRoot, 600, 600);//Add the root layout to the scene.
stage.setScene(scene);//Set the scene.
stage.setTitle("Greetings"); //creates title
stage.show();//Show the stage.
}
public static void main(String[] args)
{
launch(args);
}
}
I am not familiar with javaFX, but maybe you should try an EventHandler/ActionEvent:
button_roll.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
mylab.setText("Hello");
}
});
You should do like this:-
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
String dd = "Hello";
stage.setTitle("Greetings"); //creates title
Button button_roll = new Button("Roll");
StackPane layout1 = new StackPane();
layout1.getChildren().add(button_roll);
Scene scene1 = new Scene(layout1, 600, 600);
stage.setScene(scene1);
Label mylab = new Label();
mylab.setText(dd);
button_roll.setOnAction(e -> {
layout1.getChildren().clear();
layout1.getChildren().add(mylab);
});
stage.show();
}
When i run my code i open a window with 3 buttons to press, what i want is when i press one of the buttons that opens a new window would just "overtake" the previous window instead of opening a new one, causing me to have 2 open windows instead of 1.
Below is my GUIController:
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import java.io.IOException;
public class GUIController {
public void patientVindue(ActionEvent actionEvent) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/patientGUI.fxml"));
GridPane gridPane = loader.load();
Scene scene = new Scene(gridPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
public void lægeVindue(ActionEvent actionEvent) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/lægeGUI.fxml"));
GridPane gridPane = loader.load();
Scene scene = new Scene(gridPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
public void sundhedsprofessionelVindue(ActionEvent actionEvent) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/sundhedsprofessionelGUI.fxml"));
GridPane gridPane = loader.load();
Scene scene = new Scene(gridPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
public tilbageVindue(ActionEvent actionEvent) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/gui.fxml"));
GridPane gridPane = loader.load();
Scene scene = new Scene(gridPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
-- Adding some more information. This is the other class that i use:
public class GUI extends Application {
#Override
public void start(final Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/gui.fxml"));
GridPane gridPane = loader.load();
Scene scene = new Scene(gridPane);
stage.setScene(scene);
stage.show();
}
}
you must be making new stage for that window, i would suggest you to make stage static then pass that scene into that stage
Create one global Stage and just set the new scenes to that one stage. You are always creating a new Stage and then setting the new scene to that new stage, which is why you are always getting new windows.
MainApp that starts the login page:
public class MainApp extends Application {
private Stage primaryStage;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Access The Unicorn World");
showLogin(this.primaryStage);
}
public static void showLogin(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/Login.fxml"));
loader.setController(new LoginController(primaryStage));
Parent loginLayout = loader.load();
primaryStage.setScene(new Scene(loginLayout));
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then for the login page I have a Controller that I set above and passed the stage. In the login page I can then do the following when someone hasn't got a account and I want to open the register window:
private Stage primaryStage;
public LoginController(Stage primaryStage) {
this.primaryStage = primaryStage;
}
#FXML
void onRegisterAction(ActionEvent event) {
showRegister(this.primaryStage);
}
public static void showRegister(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/Register.fxml"));
loader.setController(new RegisterController(primaryStage));
Parent registerLayout = loader.load();
primaryStage.setScene(new Scene(registerLayout));
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
I have an example of parent and child stages, when opening the program the primaryStage is maximized, minimization (when with maximized screen mode enabled) and reopening only pull one of the child stages of the stage, the other is hidden. How should I work this kind of problem?
Note: I need the daughters to be initStyle (StageStyle.UTILITY) to concatenate the stages in just one icon in S.O.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class LotsaStages extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("JavaFX App");
primaryStage.setMaximized(true);
primaryStage.show();
Stage stage = new Stage();
stage.initStyle(StageStyle.UTILITY);
stage.initOwner(primaryStage);
stage.show();
Stage stage2 = new Stage();
stage2.initStyle(StageStyle.UTILITY);
stage2.initOwner(primaryStage);
stage2.show();
}
public static void main(String[] args) {
launch(args);
}
}
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);.
My configuration:
I need to switch between scenes via the same stage
I need to keep a maximized stage that fills the whole screen
My issue:
although I set my stage to be maximized primaryStage.setMaximized(true);it adopts its size to the size of the scenes afterwards.
What I tried until now:
I tried using primaryStage.getScene().setRoot(<the root node of scene>). While it worked to keep the stage maximized, yet after each change of scene the focus on the previously focused gui control is lost (after switch only the first gui control in the scene hierarchy is focused). I really need scenes, so that any gui control that was focused still be will focused after the stage changes its scene.
I need your assistance:
I really need your assistance in keeping the stage maximized during changing scenes.
Here is my example code:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class NewFXMain extends Application {
#Override
public void start(Stage primaryStage) {
// init buttons
Button btn1 = new Button("switch to next scene >>");
Button btn2 = new Button("<< switch to previous scene");
// first scene
StackPane root1 = new StackPane();
root1.getChildren().add(btn1);
Scene scene1 = new Scene(root1, 300, 250);
// second scene
StackPane root2 = new StackPane();
root2.getChildren().add(btn2);
Scene scene2 = new Scene(root2, 500, 400);
// button actions
btn1.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene2);
});
btn2.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene1);
});
primaryStage.setMaximized(true);
primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
SOLUTION
create scenes depending on the screen size of your monitor
after several attempts I finally figured how to easily solve this problem to keep the maximized screen while retaining the focused node on each Scene. Hope it helps the community:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class NewFXMain extends Application {
#Override
public void start(Stage primaryStage) {
// get screensize of monitor
Rectangle2D screenSize = Screen.getPrimary().getVisualBounds();
// init buttons
Button btn1 = new Button("switch to next scene >>");
Button btn2 = new Button("<< switch to previous scene");
// first rootNode
StackPane root1 = new StackPane();
root1.getChildren().add(btn1);
Scene scene1 = new Scene(root1, screenSize.getWidth(), screenSize.getHeight());
// second rootNode
StackPane root2 = new StackPane();
root2.getChildren().add(btn2);
Scene scene2 = new Scene(root2, screenSize.getWidth(), screenSize.getHeight());
// button actions
btn1.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene2);
});
btn2.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene1);
});
primaryStage.setMaximized(true); // keep this since otherwise the titlebar is bit overlapped
primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I think it's a bug. You can report it at: http://bugreport.java.com.
In the meantime, as a workaround, you probably need to just set the pane for a shared scene, replacing its content rather than replacing the scene.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class NewFXMainFixed extends Application {
#Override
public void start(Stage primaryStage) {
// init buttons
Button btn1 = new Button("switch to next scene >>");
Button btn2 = new Button("<< switch to previous scene");
// first scene
StackPane root1 = new StackPane();
root1.getChildren().add(btn1);
// second scene
StackPane root2 = new StackPane();
root2.getChildren().add(btn2);
// button actions
btn1.setOnAction((ActionEvent event) ->
primaryStage.getScene().setRoot(root2)
);
btn2.setOnAction((ActionEvent event) ->
primaryStage.getScene().setRoot(root1)
);
Scene scene = new Scene(root1);
primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}