JavaFX: form shows state, modal non-modal

Program window display generally has three modes. Non-modal and modal, where modal is divided into program modal and form modal.

Non-modal can be understood as there are no restrictions between forms, and you can use the mouse, keyboard and other tools to switch between forms.

Program modality means that after the form is opened, all the windows of the program are frozen and cannot be switched. They can only be switched after the program modal window is closed.

The form modality means that after the form is opened, all the forms traced back to the form are frozen and cannot be switched. However, if the form is opened in the program, the forms that are not on the traced line can be freely switched with the form.

The test code is as follows:

package javafx8.ch04;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
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.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;

import static javafx.stage.Modality.APPLICATION_MODAL;
import static javafx.stage.Modality.NONE;
import static javafx.stage.Modality.WINDOW_MODAL;

/**
 * @copyright 2023-2022
 * @package learnjavafx8.javafx8.ch04
 * @file StageModalityApplication.java
 * @date 2023-02-02 20:59
 * @author qiao wei
 * @version 1.0
 * @brief Sets the form modality. JavaFX is divided into 3 modalities.
 * Non-modal NONE: Defines a top-level window that is not modal and does not block any other window.
 * Program modal APPLICATION_MODAL: Defines a modal window that blocks events from being delivered to any
 * other application window.
 * Window modal WINDOW_MODAL: Defines a modal window that block events from being delivered to its entire
 * owner window hierarchy.
 * @history
 */
public class StageModalityApplication extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        // Buttons to display each kind of modal stage
        Button ownedNoneButton = new Button("Owned None");
        
        /**
         * The parent control is primaryStage, and the stage between the parent control and the child control is non-modal. The mouse can switch between the parent and child controls. When the parent control is closed, the child control
         * Close together with the parent control.
         */
        ownedNoneButton.addEventHandler(MouseEvent.MOUSE_CLICKED,
            new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    showDialog(primaryStage, NONE);
                }
            }
        );
// ownedNoneButton.setOnAction(e -> showDialog(primaryStage, NONE));
// ownedNoneButton.setOnAction(new EventHandler<ActionEvent>() {
// @Override
// public void handle(ActionEvent actionEvent) {
// showDialog(primaryStage, NONE);
// }
// });
        
        Button nonOwnedNoneButton = new Button("Non-owned None");
        
        /**
         * The parent control is null, and the relationship between primaryStage and control stage is non-modal. The mouse can switch between the two controls. When the primaryStage control is closed,
         *, the stage control is not closed.
         */
        nonOwnedNoneButton.setOnAction(e -> showDialog(null, NONE));
        
        // Form a modal with the parent window that created this window.
        Button ownedWinButton = new Button("Owned Window Modal");
        // The parent control is in the WINDOW_MODAL mode of primaryStage. It only forms a modal with the parent control and does not form a modal with the other child controls of the parent control.
        ownedWinButton.setOnAction(e -> showDialog(primaryStage, WINDOW_MODAL));
        
        Button nonOwnedWinButton = new Button("Non-owned Window Modal");
        // WINDOW_MODAL mode in which the parent control is null. Because the parent control is null, it means that the parent control and the other child controls of the parent control do not form a modal.
        nonOwnedWinButton.setOnAction(e -> showDialog(null, WINDOW_MODAL));
        
        // All windows of the program that created this window are modal.
        Button ownedAppButton = new Button("Owned Application Modal");
        // Set button opacity.
        ownedAppButton.setOpacity(0.3);
        //The parent control is the APPLICATION_MODAL mode of primaryStage, which forms a modal state with all other child controls in the Application.
        ownedAppButton.setOnAction(e -> showDialog(primaryStage, APPLICATION_MODAL));
        
        Button nonOwnedAppButton = new Button("Non-owned Application Modal");
        // The APPLICATION_MODAL mode in which the parent control is null forms a modal state with the parent control and the other child controls of the parent control.
        nonOwnedAppButton.setOnAction((ActionEvent event)
            -> showDialog(null, APPLICATION_MODAL));
                
        VBox root = new VBox();
        root.getChildren().addAll(ownedNoneButton,
                nonOwnedNoneButton,
                ownedWinButton,
                nonOwnedWinButton,
                ownedAppButton,
                nonOwnedAppButton);
        Scene scene = new Scene(root, 300, 200);
        
        primaryStage.setScene(scene);
        primaryStage.setTitle("The Primary Stage");
        
        // Set full screen and unresizable.
        primaryStage.setFullScreen(true);
// primaryStage.setResizable(false);
        
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        Application.launch(StageModalityApplication.class, args);
    }
    
    /**
     * @class StageModalityApplication
     * @date 2023-06-21 21:01
     * @author qiao wei
     * @version 1.0
     * @brief Set window state based on window owner and mode.
     * @param owner The parent control of the window.
     * @param modality window mode.
     * @return
     * @throws
     */
    private void showDialog(Window owner, Modality modality) {
        // Create a new stage with specified owner and modality
        Stage stage = new Stage();
        
        // Set the stage owner and modality
        stage.initOwner(owner);
        stage.initModality(modality);
        
        Label modalityLabel = new Label(modality.toString());
        Button closeButton = new Button("Close");
// closeButton.setOnAction(e -> stage.close());
        closeButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> stage.close());

        VBox root = new VBox();
        root.getChildren().addAll(modalityLabel, closeButton);
        Scene scene = new Scene(root, 200, 100);
        
        //Set the display mode of the mouse in the scene
        scene.setCursor(Cursor.HAND);
        
        stage.setScene(scene);
        stage.setTitle("A Dialog Box");
        stage.show();
    }
}