【问题标题】:JavaFX testing whether application is closing as a whole or just individual windowJavaFX 测试应用程序是作为一个整体关闭还是只是单个窗口关闭
【发布时间】:2023-04-10 16:32:01
【问题描述】:

我有一个可以打开多个窗口的 JavaFX 应用程序。每当从该窗口失去焦点时,该窗口内的数据就会记录到数据库中。 当用户想要关闭窗口时,应该触发一个事件处理程序,请求从数据库中删除元组。 我希望当用户主动点击窗口右上角的 x 时发生这种情况,而在应用程序完全退出时发生(例如,如果程序从操作系统启动栏或等效项)或以其他方式停止。

关闭事件处理程序存根类似于以下内容:

foo.setOnCloseRequest(new EventHandler<WindowEvent>() 
  {      
    @Override
    public void handle(WindowEvent event)
    {          
      try
      {
        barController.exec(Action.DELETE, item);     
      } catch (Exception e)
      {
        e.printStackTrace();
      }
    }
  });

问题是,当我从 Ubuntu 的栏中停止程序时(例如),仍然为每个窗口调用此事件;并且每次测试的事件是WindowEvent.WINDOW_CLOSE_REQUEST 用户或应用程序是否关闭了窗口。

简单地说:有什么方法可以从“onCloseApplication”中划定“onUserCloseWindow”吗?

【问题讨论】:

  • 您可以在后台执行数据库工作,在窗口关闭后不久。 (我个人会使用 30 秒的延迟。)
  • @VGR,除了在程序的可视化组件停止运行后让 GUI 驱动的应用程序执行具有潜在风险的后台任务的固有问题之外,您仍然会遇到同样的问题:应用程序无法知道哪些项目已被提名删除,哪些没有。我能看到的唯一简单且合理可行的解决方法是在窗口关闭时将关闭事件添加到时间戳队列中。那么您可以让 Application.stop() 测试任何早于最后一秒的时间戳,并相应地删除相关的。

标签: java javafx


【解决方案1】:

当使用原生窗口装饰时,我不相信有办法区分这些类型的事件。从您的应用的角度来看,它们都是

关闭此窗口的外部请求

.

我认为您最好的选择是实现您自己的窗口装饰,如 here 所述。

【讨论】:

  • 这是一个合理的建议,虽然感觉就像用大锤敲碎坚果。我提出了一种解决方法,我认为这是一个合理的折衷方案。
  • 我不反对 ;)
【解决方案2】:

看起来,当您从任务栏(至少在 Mac 上)关闭时,所有者窗口会在事件传递到其他子窗口之前获得关闭请求事件。因此,您可以检测所有者的关闭请求事件,设置一个标志,当其他窗口收到他们的关闭请求时,他们可以在执行处理之前检查标志是否已设置。如果设置了标志,则它是一个任务栏或用户启动的整个应用程序的关闭,否则它是一个用户启动的仅关闭一个辅助窗口。

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Eventacity extends Application {
    private boolean isPrimaryClosing = false;

    @Override
    public void start(Stage primary) {
        primary.setScene(new Scene(new Group(), 200, 200));
        primary.setTitle("Main");
        addEventHandlers(primary);
        primary.show();

        for (int i = 0; i < 3; i++) {
            Stage secondary = new Stage();
            secondary.setTitle("Secondary " + i);
            secondary.setScene(new Scene(new Group(), 100, 100));
            secondary.setX(primary.getX() + (i+1) * 25);
            secondary.setY(primary.getY() + (i+1) * 25);

            secondary.initOwner(primary);
            addEventHandlers(secondary);

            secondary.show();
        }
    }

    private void addEventHandlers(Stage stage) {
        stage.setOnCloseRequest(event -> {
            if (stage.getOwner() == null) {
                isPrimaryClosing = true;
            }

            System.out.println(
                    "Close Request:   " + stage.getTitle()
            );
            System.out.println(
                    "Primary Closing: " + isPrimaryClosing
            );

            if (!isPrimaryClosing) {
                // delete data from database.
            }
        });
        stage.setOnHiding(event -> System.out.println(
                "Hiding:          " + stage.getTitle())
        );
        stage.setOnHidden(event -> System.out.println(
                "Hid:             " + stage.getTitle())
        );
        stage.setOnShowing(event -> System.out.println(
                "Showing:         " + stage.getTitle())
        );
        stage.setOnShown(event -> System.out.println(
                "Showed:          " + stage.getTitle())
        );
    }

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

【讨论】:

  • 适用于某些情况的合理解决方法。可悲的是,要创建的窗口数量仅在运行时才知道,并且 Ubuntu 最后关闭了“主窗口”。这让我真的回到了同样的问题!时间戳和 50 毫秒的延迟正在我的主 PC 上运行。我唯一担心的是它在旧机器上的可靠性可能会稍差一些,从而导致数据库中出现一些伪影。不是世界末日,但不是理想!
【解决方案3】:

最好的方法似乎是测试舞台是否有焦点。按 X 应始终处于焦点位置。因此,如果在焦点窗口上调用关闭请求,则会发送删除请求。这似乎没有考虑像“Alt-F4”这样的动作,但这可以被证明是一个“功能”。它不是商业应用程序,只是我想为图形 Linux 环境编写的有用工具。

if (foo.focusedProperty().getValue()) {
            try
            {
              barController.exec(Action.DELETE, fooId);
            } catch (Exception e)
            {
              e.printStackTrace();
            }
          }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2011-09-19
    • 2011-05-15
    • 2020-05-02
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 2016-06-21
    相关资源
    最近更新 更多