JavaFX

JavaFX Stage Example

This is a JavaFX Stage Example. A Stage in JavaFX is a top-level container that hosts a Scene, which consists of visual elements. The Stage class in the javafx.stage package represents a stage in a JavaFX application. The primary stage is created by the platform and passed to the start(Stage s) method of the Application class. You can create additional stages as needed.

A Stage object must be created and modified on the JavaFX Application Thread. Recall that the start() method of the Application class is called on the JavaFX Application Thread, and a primary Stage is created and passed to this method.

Note that the primary stage that is passed the start() method is not shown. You need to call the show() method to show it.

 
The following table shows an overview of the whole article:

The following examples use Java SE 7 and JavaFX 2.2.

1. Knowing the Details of Your Screens

1.1 The Code

FxStageExample1.java

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.geometry.Rectangle2D;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class FxStageExample1 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(Stage stage) 
	{
		// Create the ScreenList
		ObservableList<Screen> screenList = Screen.getScreens();
		
		System.out.println("Screens Count: " + screenList.size());
		// Print the details of all screens
		for(Screen screen: screenList) 
		{
			print(screen);
		}
		
		// Exit the Program
		Platform.exit();
	}
	
	public void print(Screen s) 
	{
		// Print the DPI
		System.out.println("DPI: " + s.getDpi());
		// Print the Bounds
		System.out.print("Screen Bounds: ");
		Rectangle2D bounds = s.getBounds();
		print(bounds);
		// Print the Visual Bounds
		System.out.print("Screen Visual Bounds: ");
		Rectangle2D visualBounds = s.getVisualBounds();
		print(visualBounds);
	}
	
	public void print(Rectangle2D r) 
	{
		// Format the Output
		System.out.format("minX=%.2f, minY=%.2f, width=%.2f, height=%.2f%n",
		r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
	}	
}

The Screen class in the javafx.stage package is used to get the details, for example, dots-per-inch (DPI) setting and dimensions of user screens (or monitors). If multiple screens are hooked up to a computer, one of the screens is known as the primary screen and others as nonprimary screens. You can get the reference of the Screen object for the primary monitor using the static getPrimary() method of the Screen class with the following code:

// Get the reference to the primary screen
Screen primaryScreen = Screen.getPrimary();

The static getScreens() method returns an ObservableList of Screen objects:

ObservableList screenList = Screen.getScreens();

You can get the resolution of a screen in DPI using the getDpi() method of the Screen class as follows:

Screen primaryScreen = Screen.getPrimary();
double dpi = primaryScreen.getDpi();

You can use the getBounds() and getVisualBounds() methods to get the bounds and visual bounds, respectively. Both methods return a Rectangle2D object, which encapsulates the (x, y) coordinates of the upper-left and the lower-right corners, the width, and the height of a rectangle.

The getMinX() and getMinY() methods return the x and y coordinates of the upper-left corner of the rectangle, respectively.

The getMaxX() and getMaxY() methods return the x and y coordinates of the lower-right corner of the rectangle, respectively.

The getWidth() and getHeight() methods return the width and height of the rectangle, respectively.

// Format the Output
System.out.format("minX=%.2f, minY=%.2f, width=%.2f, height=%.2f%n",
r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());

The bounds of a screen cover the area that is available on the screen. The visual bounds represent the area on the screen that is available for use, after taking into account the area used by the native windowing system such as task bars and menus. Typically, but not necessarily, the visual bounds of a screen represents a smaller area than its bounds.

If a desktop spans multiple screens, the bounds of the nonprimary screens are relative to the primary screen.

1.2 The Output

Screens Count: 1
DPI: 100.0
Screen Bounds: minX=0,00, minY=0,00, width=1366,00, height=768,00
Screen Visual Bounds: minX=0,00, minY=0,00, width=1366,00, height=728,00

2. Showing the Primary Stage

2.1 The Code

FxStageExample2.java

import javafx.application.Application;
import javafx.stage.Stage;

public class FxStageExample2 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(Stage stage) 
	{
		// Display the Stage
		stage.show();
		// Close the Stage
		stage.close();
	}
	
}

The start() method has no code. When you run the application, you do not see a window, nor do you see output on the console. The application runs forever. You will need to use the system-specific keys to cancel the application.

@Override
public void start(Stage stage) 
{
	stage.close(); // Close the only stage you have
}

If you are using Windows, use your favorite key combination Ctrl + Alt + Del to activate the task manager! If you are using the command prompt, use Ctrl + C.

Recall that JavaFX Application Thread is terminated when the Platform.exit() method is called or the last shown stage is closed.

@Override
public void start(Stage stage) 
{
	Platform.exit(); // Exit the application
}

The JVM terminates when all nondaemon threads die. JavaFX Application Thread is a nondaemon thread. The Application.launch() method returns when
the JavaFX Application Thread terminates.

The close() method does not close the stage if the stage is not showing.

@Override
public void start(Stage stage) 
{
	stage.close(); // Close the only stage you have
}

The following code will show and close the stage:

// Display the Stage
stage.show();
// Close the Stage
stage.close();

3. Setting the Bounds of a Stage

3.1 The Code

FxStageExample3.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FxStageExample3 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(Stage stage) 
	{
		// Set the title of the Stage
		stage.setTitle("Stage with a Button in the Scene");
		// Create the Button
		Button button = new Button("Hello");
		// Create the VBox
		VBox root = new VBox(button);
		// Create the Scene
		Scene scene = new Scene(root, 200, 100);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the width and height of the Stage
		stage.setWidth(400);
		stage.setHeight(100);
		// Display the Stage
		stage.show();		
	}
	
}

The bounds of a Stage consist of four properties: x, y, width, and height. The x and y properties determine the location (or position) of the upper-left corner of the stage. The width and height properties determine its size. You can use the getters and setters for these properties to get and set their values.

Let’s add a Button to the Scene and set the scene width and height to 300 and 100, respectively, as follows:

@Override
public void start(Stage stage) 
{
		// Set the title of the Stage
		stage.setTitle("Stage with a Button in the Scene");
		// Create the Button
		Button button = new Button("Hello");
		// Create the VBox
		VBox root = new VBox(button);
		// Create the Scene
		Scene scene = new Scene(root, 200, 100);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the width and height of the Stage
		stage.setWidth(400);
		stage.setHeight(100);
		// Display the Stage
		stage.show();		
}

3.2 The GUI

The following image shows a Stage with a Scene that contains a Button where the size of the Scene is not specified.

Setting the Bounds of a JavaFX Stage
Setting the Bounds of a JavaFX Stage

4. Initializing the Style of a Stage

4.1 The Code

FxStageExample4.java

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class FxStageExample4 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(final Stage stage) 
	{
		// Create the Label
		Label styleLabel = new Label("Stage Style");
		// Create the Button
		Button closeButton = new Button("Close");
		// Add an EventHandler to the Button
		closeButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	stage.close();
            }
        });		
            
		// Create the VBOx
		VBox root = new VBox();
		// Add the Children to the VBox
		root.getChildren().addAll(styleLabel, closeButton);

		// Create the Scene
		Scene scene = new Scene(root, 200, 100);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("The Style of a Stage");
		// Display the Stage
		this.show(stage, styleLabel, StageStyle.DECORATED);
		//this.show(stage, styleLabel, UNDECORATED);
		//this.show(stage, styleLabel, TRANSPARENT);
		//this.show(stage, styleLabel, UNIFIED);
		//this.show(stage, styleLabel, UTILITY);
	}
	
	private void show(Stage stage, Label styleLabel, StageStyle style) 
	{
		// Set the text for the label to match the style
		styleLabel.setText(style.toString());
		// Set the style
		stage.initStyle(style);
		
		// For a transparent style, set the scene fill to null. Otherwise, the
		// content area will have the default white background of the scene.
		if (style == StageStyle.TRANSPARENT) 
		{
			stage.getScene().setFill(null);
			stage.getScene().getRoot().setStyle("-fx-background-color: transparent");
		} 
		else if(style == StageStyle.UNIFIED) 
		{
			stage.getScene().setFill(Color.TRANSPARENT);
		}
		
		// Display the stage
		stage.show();
	}	
}

The area of a Stage can be divided into two parts: content area and decorations.

The content area displays the visual content of its Scene. Typically, decorations consist of a title bar and borders. The presence of a title bar and its content varies depending on the type of decorations provided by the platform. Some decorations provide additional features rather than just an aesthetic look.

For example, a title bar may be used to drag a stage to a different location. Different buttons in a title bar may be used to minimize, maximize, restore, and close a Stage.

In JavaFX, the style attribute of a Stage determines its background color and decorations. Based on styles, you can have the following five types of stages in JavaFX:

  • Decorated
  • Undecorated
  • Transparent
  • Unified
  • Utility

A decorated Stage has a solid white background and platform decorations.

An undecorated Stage has a solid white background and no decorations.

A transparent Stage has a transparent background and no decorations.

A unified Stage has platform decorations and no border between the client area and decorations. The client area background is unified with the decorations. To see the effect of the unified stage style, the Scene should be filled with Color.TRANSPARENT. Unified style is a conditional feature. A utility stage has a solid white background and minimal platform decorations.

You can set the style of a stage using the initStyle(StageStyle style) method of the Stage class. The style of a stage must be set before it is shown for the first time. Setting it the second time, after the stage has been shown, throws a runtime exception.

By default, a stage is decorated.

The five types of styles for a stage are defined as five constants in the StageStyle enum:

  • StageStyle.DECORATED
  • StageStyle.UNDECORATED
  • StageStyle.TRANSPARENT
  • StageStyle.UNIFIED
  • StageStyle.UTILITY

4.2 The GUI

The following figure shows the Stage using the StageStyle.DECORATED style.

Initializing the Style of a JavaFX Stage
Initializing the Style of a JavaFX Stage

5. Moving an Undecorated Stage

5.1 The Code

FxStageExample5.java

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class FxStageExample5 extends Application
{
	private Stage stage;
	private double dragOffsetX;
	private double dragOffsetY;
	
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(final Stage stage) 
	{
		// Store the stage reference in the instance variable to
		// use it in the mouse pressed event handler later.
		this.stage = stage;
		// Create the Label
		Label msgLabel = new Label("Press the mouse button and drag.");
		// Create the Button
		Button closeButton = new Button("Close");
		// Add the EventHandler to the Button
		closeButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	stage.close();
            }
        });		

		// Create the VBox
		VBox root = new VBox();
		// Add the children to the VBox
		root.getChildren().addAll(msgLabel, closeButton);
		
		// Create the Scene
		Scene scene = new Scene(root, 300, 200);		
		// Set mouse pressed and dragged even handlers for the scene
		scene.setOnMousePressed(new EventHandler<MouseEvent>() 
		{
	        @Override
	        public void handle(MouseEvent event) 
	        {
	        	handleMousePressed(event);
	        }
	    });
		scene.setOnMouseDragged(new EventHandler<MouseEvent>() 
		{
	        @Override
	        public void handle(MouseEvent event) 
	        {
	        	handleMouseDragged(event);
	        }
	    });
		
		// Add the Scene to The Stager
		stage.setScene(scene);
		// Set the Title
		stage.setTitle("Moving a Stage");
		// Set the Style for the Stage
		stage.initStyle(StageStyle.UNDECORATED);
		// Display the Stage
		stage.show();
	}
	
	protected void handleMousePressed(MouseEvent e) 
	{
		// Store the mouse x and y coordinates with respect to the
		// stage in the reference variables to use them in the drag event
		this.dragOffsetX = e.getScreenX() - stage.getX();
		this.dragOffsetY = e.getScreenY() - stage.getY();
	}
	
	protected void handleMouseDragged(MouseEvent e) 
	{
		// Move the stage by the drag amount
		stage.setX(e.getScreenX() - this.dragOffsetX);
		stage.setY(e.getScreenY() - this.dragOffsetY);
	}	
}

You can move a stage to a different location by dragging its title bar. In an undecorated or transparent stage, a title bar is not available. You need to write a few lines of code to let the user move this kind of stage by dragging the mouse over the scene area.

The above example show how to write the code to support dragging of a Stage. If you change the Stage to be transparent, you will need to drag the stage by dragging the mouse over only the message label, as the transparent area will not respond to the mouse events.

The following snippet of code adds the mouse pressed and mouse dragged event handlers to the Scene:

// Set mouse pressed and dragged even handlers for the scene
scene.setOnMousePressed(new EventHandler<MouseEvent>() 
{
	@Override
	public void handle(MouseEvent event) 
	{
		handleMousePressed(event);
	}
});
scene.setOnMouseDragged(new EventHandler<MouseEvent>() 
{
	@Override
	public void handle(MouseEvent event) 
	{
		handleMouseDragged(event);
	}
});

When you press the mouse in the scene, the handleMousePressed() method is called. The getScreenX() and getScreenY() methods of the MouseEvent object return the x and y coordinates of the mouse with respect to the upper-left corner of the screen.

When you drag the mouse, the handleMouseDragged() method is called. The method computes and sets the position of the Stage using the position of the mouse when it was pressed and its position during the drag.

5.2 The GUI

The following image shows a Stage, which can be moved by the mouse handlers.

Moving an undecorated JavaFX Stage
Moving an undecorated JavaFX Stage

6. Initializing Modality of a Stage

6.1 The Code

FxStageExample6.java

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;

public class FxStageExample6 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(final Stage stage) 
	{
		/* Create the Buttons to display each kind of modal stage */
		Button ownedNoneButton = new Button("Owned None");
		ownedNoneButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	showDialog(stage, Modality.APPLICATION_MODAL);
            }
        });	
		
		Button nonOwnedNoneButton = new Button("Non-owned None");
		nonOwnedNoneButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	showDialog(stage, Modality.APPLICATION_MODAL);
            }
        });	
		
		Button ownedWinButton = new Button("Owned Window Modal");
		ownedWinButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	showDialog(stage, Modality.APPLICATION_MODAL);
            }
        });	
		
		Button nonOwnedWinButton = new Button("Non-owned Window Modal");
		nonOwnedWinButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	showDialog(stage, Modality.APPLICATION_MODAL);
            }
        });	
		
		Button ownedAppButton = new Button("Owned Application Modal");
		ownedAppButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	showDialog(stage, Modality.APPLICATION_MODAL);
            }
        });	
		
		Button nonOwnedAppButton = new Button("Non-owned Application Modal");
		nonOwnedAppButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	showDialog(stage, Modality.APPLICATION_MODAL);
            }
        });		
		
		// Create the VBox
		VBox root = new VBox();
		// Add the children to the VBox
		root.getChildren().addAll(ownedNoneButton, nonOwnedNoneButton,
		ownedWinButton, nonOwnedWinButton,ownedAppButton, nonOwnedAppButton);
		
		// Create the Scene
		Scene scene = new Scene(root, 300, 200);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("The Primary Stage");
		// Display the Stage
		stage.show();
	}
	
	private void showDialog(Window owner, Modality modality) 
	{
		// Create a Stage with specified owner and modality
		final Stage stage = new Stage();
		stage.initOwner(owner);
		stage.initModality(modality);
		
		// Create the Label
		Label modalityLabel = new Label(modality.toString());
		// Create the Button
		Button closeButton = new Button("Close");
		// Add the EventHandler to the Button
		closeButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	stage.close();
            }
        });		

		// Create the VBox
		VBox root = new VBox();
		// Add the Children to the VBox
		root.getChildren().addAll(modalityLabel, closeButton);
		
		// Create the Scene
		Scene scene = new Scene(root, 200, 100);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("A Dialog Box");
		// Display the Stage
		stage.show();
	}
}

In a GUI application, you can have two types of windows: modal and modeless. When a modal window is displayed, the user cannot work with other windows in the application until the modal window is dismissed. If an application has multiple modeless windows showing, the user can switch between them at any time.

JavaFX has three types of modality for a stage:

  • None
  • Window modal
  • Application modal

Modality of a Stage is defined by one of the following three constants in the Modality enum in the javafx.stage package:

  • NONE
  • WINDOW_MODAL
  • APPLICATION_MODAL

You can set the modality of a stage using the initModality(Modality m) method of the Stage class as follows:

// Create a Stage object and set its modality
Stage stage = new Stage();
stage.initModality(Modality.WINDOW_MODAL);

/* More code goes here.*/

// Show the stage
stage.show();

A Stage can have an owner. An owner of a Stage is another Window. You can set an owner of a Stage using the initOwner(Window owner) method of the Stage class.

The owner of a Stage must be set before the stage is shown. The owner of a Stage may be null, and in this case, it is said that the Stage does not have an owner. Setting an owner of a Stage creates an owner-owned relationship. For example, a Stage is minimized or hidden if its owner is minimized or hidden, respectively.

The default modality of a Stage is NONE. When a Stage with the modality NONE is displayed, it does not block any other windows in the application. It behaves as a modeless window. A Stage with the WINDOW_MODAL modality blocks all windows in its owner hierarchy.

If a Stage with its modality set to APPLICATION_MODAL is displayed, you must work with the Stage and dismiss it before you can work with any other windows in the application.

Notice that an APPLICATION_MODAL stage blocks all other windows in the same application, irrespective of the owner-owned relationships.

6.2 The GUI

The following image displays the primary stage with six buttons. Each button opens a secondary stage with a specified modality and owner. The text of the buttons tells you what kind of secondary stage they will open.

Initializing Modality of a JavaFX Stage
Initializing Modality of a JavaFX Stage

When the secondary stage is shown, try clicking on the primary stage. When the modality of the secondary stage blocks the primary stage, you will not be able to
work with the primary stage; clicking the primary stage will set the focus back to the secondary stage.

Setting the Modality of a JavaFX Stage to APPLICATION_MODAL
Setting the Modality of a JavaFX Stage to APPLICATION_MODAL

7. Resizing a Stage

7.1 The Code

FxStageExample7.java

import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class FxStageExample7 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(Stage stage) 
	{
		// Create the Group
		Group group = new Group();
		// Create the Scene
		Scene scene = new Scene(group);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("A Maximized Stage");
		// Set the position and size of the stage equal to the position and
		// size of the screen
		Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
		stage.setX(visualBounds.getMinX());
		stage.setY(visualBounds.getMinY());
		stage.setWidth(visualBounds.getWidth());
		stage.setHeight(visualBounds.getHeight());
		// Display the Stage
		stage.show();
	}
	
}

You can set whether a user can or cannot resize a stage by using its setResizable(boolean resizable) method.

Note that a call to the setResizable() method is a hint to the implementation to make the stage resizable. By default, a stage is resizable.

Sometimes, you may want to restrict the use to resize a stage within a range of width and height. The setMinWidth(), setMinHeight(), setMaxWidth(), and setMaxHeight() methods of the Stage class let you set the range within which the user can resize a stage.

7.2 The GUI

The following image shows resizeable Stage.

Resizing a JavaFX Stage
Resizing a JavaFX Stage

8. Showing a Stage and Waiting for It to Close

8.1 The Code

FxStageExample8.java

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FxStageExample8 extends Application
{
	// Create the counter
	protected static int counter = 0;
	// Create the Stage
	protected Stage lastOpenStage;
	// Create the TextArea
	protected TextArea area = new TextArea();
	
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	public void start(Stage stage) 
	{
		// Create the VBox
		VBox root = new VBox();
		// Create the Button
		Button openButton = new Button("Open");
		// Add the EventHandler to the button
		openButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	open(++counter);
            }
        });		
		
		// Add the children to the VBox
		root.getChildren().addAll(openButton,area);
		
		// Create the Scene
		Scene scene = new Scene(root, 400, 400);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("The Primary Stage");
		// Display the Stage
		stage.show();
		// Set the Stage as the last opened Stage
		this.lastOpenStage = stage;
	}
	
	private void open(final int stageNumber) 
	{
		// Create a new Stage
		Stage stage = new Stage();
		// Set the Title of the Stage
		stage.setTitle("#" + stageNumber);
		// Create a Say-Hello-Button
		Button sayHelloButton = new Button("Say Hello");
		// Add the EventHandler to the Button
		sayHelloButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	area.appendText("Hello from #" + stageNumber + "\n");
            }
        });		
		
		// Create an Open Button
		Button openButton = new Button("Open");
		// Add the EventHandler to the Button
		openButton.setOnAction(new EventHandler <ActionEvent>() 
		{
            public void handle(ActionEvent event) 
            {
            	open(++counter);
            }
        });		
		
		// Create the VBox
		VBox root = new VBox();
		// Add the children to the VBox
		root.getChildren().addAll(sayHelloButton, openButton);
		
		// Create the Scene
		Scene scene = new Scene(root, 200, 200);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Position of the Stage
		stage.setX(this.lastOpenStage.getX() + 50);
		stage.setY(this.lastOpenStage.getY() + 50);
		// Set the current Stage as the last opened Stage
		this.lastOpenStage = stage;
		area.appendText("Before stage.showAndWait(): " + stageNumber + "\n");		
		// Show the Stage and wait for it to close
		stage.showAndWait();		
		area.appendText("After stage.showAndWait(): " + stageNumber + "\n");
	}	
}

You often want to display a dialog box and suspend further processing until it is closed. For example, you may want to display a message box to the user with options to click yes and no buttons, and you want different actions performed based on which button is clicked by the user. In this case, when the message box is displayed to the user, the program must wait for it to close before it executes the next sequence of logic.

Consider the following pseudo-code:

Option userSelection = messageBox("Close", "Do you want to exit?", YESNO);
if (userSelection == YES) 
{
        stage.close();
}

In this pseudo-code, when the messageBox() method is called, the program needs to wait to execute the subsequent if statement until the message box is dismissed.

The show() method of the Window class returns immediately, making it useless to open a dialog box in the above example. You need to use the showAndWait() method, which shows the stage and waits for it to close before returning to the caller. The showAndWait() method stops processing the current event temporarily and starts a nested event loop to process other events.

You can have multiple stages open using the showAndWait() method. Each call to the method starts a new nested event loop. A specific call to the method returns to the caller when all nested event loops created after this method call have terminated.
This rule may be confusing in the beginning. Let’s look at an example to explain this in detail. Suppose you have three stages: s1, s2, and s3. Stage s1 is opened using the call s1.showAndWait(). From the code in s1, stage s2 is opened using the call s2.showAndWait(). At this point, there are two nested event loops: one created by s1.showAndWait() and another by s2.showAndWait(). The call to s1.showAndWait() will return only after both s1 and s2 have been closed, irrespective of the order they were closed. The s2.showAndWait() call will return after s2 has been closed.

8.2 The GUI

The following image shows a program that will allow you to play with the showAndWait() method call using multiple stages.

The primary stage is opened with an Open button. Clicking the Open button opens a
secondary Stage using the showAndWait() method.

Showing a JavaFX Stage and Waiting for It to Close
Showing a JavaFX Stage and Waiting for It to Close

The secondary stage has two buttons—Say Hello and Open—which will, respectively, will print a message on the console and open another secondary Stage.

A message is printed on the console before and after the call to the showAndWait() method.

Showing a JavaFX Children Stage and Waiting for It to Close
Showing a JavaFX Children Stage and Waiting for It to Close

You need to open multiple secondary stages, print messages by clicking the Say Hello Button, close them in any order you want, and then look at the output on the console.

9. Download Java Source Code

This was an example of avafx.stage

Download
You can download the full source code of this example here: JavaFxStageExample.zip

Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button