【问题标题】:JavaFX - Make any other stages close when the main stage is closed, yet allow them to be hidden behind the main stageJavaFX - 当主阶段关闭时关闭任何其他阶段,但允许它们隐藏在主阶段后面
【发布时间】:2015-08-03 08:15:39
【问题描述】:

假设我有以下代码用于我正在创建的第二个窗口:

    stage.initModality(Modality.NONE);
    stage.initOwner(coreController.getStage());

如果我这样做,它会在我的主窗口关闭时关闭。

如果我注释掉stage.initOwner(coreController.getStage());,那么它可以隐藏在主面板后面,但不会关闭。

当我杀死主阶段时,有什么方法可以关闭它... 而不编写代码来跟踪创建的每个新窗口?到目前为止,似乎我唯一的选择是在列表中注册每个新窗口,当主窗口触发“关闭事件”时,我也会为所有其他窗口触发这个。有没有办法让我不必像那样进去把所有东西都连接在一起?

编辑:我使用了 Modality.NONE 以便窗口不会阻止任何事件,但是我不知道这是否与问题相关。

编辑 2: 我希望在退出主窗口时关闭所有窗口(如果我能拦截关闭事件并进行清理,那将是一个奖励)。

【问题讨论】:

  • 您想在主窗口关闭时退出整个应用程序吗?这不是您所要求的 - 但如果可行,则设置起来很容易。否则,除了按照您的描述跟踪窗口之外,我看不到其他方法。
  • @James_D 是的,这是正确的,让我将其添加到主帖中。对不起,我不够清楚。编辑 2 应该描述这一点(如果可能的话,加上一个可能的奖金)。

标签: java javafx window


【解决方案1】:

如果您只想关闭所有子窗口,但出于其他原因保持应用程序运行(例如,您打开了同级窗口等...),那么我认为您必须按照您在问题(保留一个窗口列表并单独调用hide(),等等)。

如果你真的打算退出应用程序,那么你可以这样做:

mainWindow.setOnHidden(e -> Platform.exit());

这将导致 JavaFX 系统正常退出(这当然会导致其他每个窗口都关闭)。

如果您需要清理资源,您可以在您的应用程序子类中重写stop(),并在该方法中清理资源。通过Platform.exit() 关闭应用程序时将调用stop()(但请注意,如果您执行System.exit(...),则不会调用它)。

如果您需要在每个窗口的基础上清理资源,那么您可以在每个窗口中注册onHidden() 处理程序来执行此操作。请注意,如果您随后 show() 隐藏了相同的窗口实例,这意味着您可能需要恢复这些资源。不过,这个用例非常不典型。

这是一个简单的例子:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class ExitOnMainWindowClose extends Application {

    @Override
    public void start(Stage primaryStage) {
        Button newWindowButton = new Button("New Window");
        newWindowButton.setOnAction(e -> showNewWindow());
        primaryStage.setScene(new Scene(new StackPane(newWindowButton), 120, 75));
        primaryStage.setOnHidden(e -> Platform.exit());
        primaryStage.show();
    }

    @Override
    public void stop() {
        System.out.println("Application-level cleanup...");
    }

    private void showNewWindow() {
        Stage stage = new Stage();
        stage.setScene(new Scene(new StackPane(new Label("New Window")), 180, 60));
        stage.setOnHidden(e -> System.out.println("Window-level cleanup..."));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

【讨论】:

    【解决方案2】:

    如果我正确理解了这个问题,您可以在主要阶段关闭时为您需要关闭的每个阶段调用 initOwner(mainStage)。

    只是添加了对 Oracle 文档的引用,这解释了为什么 initOwner(mainStage) 不适合这种情况:

    一个阶段可以选择拥有一个所有者窗口。当一个窗口是一个阶段的所有者时,它被称为该阶段的父级。当父窗口关闭时,其所有子窗口都将关闭。相同的链接行为适用于图标化的父窗口。 舞台将始终位于其父窗口的顶部。必须在舞台可见之前初始化所有者。

    发件人:https://docs.oracle.com/javase/8/javafx/api/javafx/stage/Stage.html#initOwner-javafx.stage.Window-

    【讨论】:

    • 但是“一个阶段将始终位于其父窗口之上”是 OP 所说的他希望避免的行为。
    • 是的,对不起。这个问题对我来说不是很清楚:S 我编辑我的答案以留下参考。
    猜你喜欢
    • 1970-01-01
    • 2012-08-25
    • 2012-10-17
    • 2012-04-30
    • 1970-01-01
    • 2014-04-21
    • 2014-07-10
    • 2014-12-24
    相关资源
    最近更新 更多