Java 检测应用程序何时关闭

Java detect when application is closing

几年前我学了Java大约1年。现在我想回去,但我的技能有点生疏了。因此,我将 Eclipse 与 WindowBuilder 一起使用来制作一个简单的表单应用程序,以便重新开始。我想在退出应用程序时弹出 window,因为在未来的项目中,当应用程序通过我自己的退出按钮以外的其他方式退出时,我需要执行一些代码(例如通过红叉或 Alt+ F4).

到目前为止,这是我的代码:

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


public class Mainframe {

private JFrame frame;

/**
 * Launch the application.
 */
public static void main(String[] args) {


    Runtime.getRuntime().addShutdownHook(new Thread()
    {
        @Override
        public void run()
        {
            JOptionPane.showConfirmDialog(null, "Do you", "Message", 
                    JOptionPane.YES_NO_OPTION);
            MessageBox.infoBox("YOUR INFORMATION HERE", "TITLE BAR MESSAGE");
        }
    });

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Mainframe window = new Mainframe();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

}

/**
 * Create the application.
 */
public Mainframe() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton btnNewButton = new JButton("New button");
    btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            System.exit(0);


        }
    });
    frame.getContentPane().add(btnNewButton, BorderLayout.SOUTH);
}



}

我使用了 this 中 "when the Application is being exited" 的代码 例如,但无论我如何关闭它,都没有"Messagebox is appearing"。当我直接在 main void 之后使用 MessageBoxes 的代码时,MessageBoxes 出现了,所以我想我放错了 ShutdownHook。

如果有人能帮我解决这个问题,我将不胜感激。

关闭挂钩用于在应用程序关闭后(通过 System.exit 调用或来自 OS).它不适用于此类对话。

您需要向 JFrame 添加 WindowListener,并对 windowClosing and/or windowClosed 事件执行操作。在这个侦听器中,您可以显示一个对话框或任何您想要的内容。

如果您希望能够覆盖 window 的关闭,您可以在 this question.

上找到有关如何操作的详细信息

我参加这里的派对有点晚了,但我想我会加 2 美分。我认为最好使用允许关闭侦听器的静态 class。它不那么复杂,并且允许检查 JVM 当前是否正在关闭(例如:隐藏日志消息)。这是我使用的实现:

import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

public enum ShutdownNotifier {
    INSTANCE;

    private static final Class<?> THIS_CLASS = new Object() {
    }.getClass().getEnclosingClass();
    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(THIS_CLASS);

    private Set<AutoCloseable> _listeners;
    private CompletableFuture<Void> _shutdownFuture;

    public boolean isShuttingDown() {
        return getShutdownFuture().isDone();
    }

    public boolean addListener(AutoCloseable listener) {
        if (listener == null)
            return false;
        var listeners = this.getListeners();
        boolean added;
        synchronized (listeners) {
            added = listeners.add(listener);
        }
        if (this.isShuttingDown()) {
            this.notifyListeners();
            return true;
        }
        return added;
    }

    public boolean removeListener(AutoCloseable listener) {
        if (listener == null)
            return false;
        var listeners = getListeners(false);
        if (listeners == null)
            return false;
        synchronized (listeners) {
            return listeners.remove(listener);
        }
    }

    private Set<AutoCloseable> getListeners() {
        return getListeners(true);
    }

    private Set<AutoCloseable> getListeners(boolean create) {
        if (_listeners == null && create)
            synchronized (this) {
                if (_listeners == null && create)
                    _listeners = new HashSet<>();
            }
        return _listeners;
    }

    private CompletableFuture<Void> getShutdownFuture() {
        if (_shutdownFuture == null)
            synchronized (this) {
                if (_shutdownFuture == null) {
                    var future = new CompletableFuture<Void>();
                    future.whenComplete((v, t) -> {
                        notifyListeners();
                    });
                    try {
                        Runtime.getRuntime().addShutdownHook(new Thread(() -> future.complete(null)));
                    } catch (IllegalStateException e) {
                        future.complete(null);
                    }
                    _shutdownFuture = future;
                }
            }
        return _shutdownFuture;
    }

    private void notifyListeners() {
        var listeners = getListeners(false);
        if (listeners == null)
            return;
        while (true) {
            AutoCloseable listener;
            synchronized (listeners) {
                var iter = listeners.iterator();
                if (!iter.hasNext())
                    break;
                listener = iter.next();
                iter.remove();
            }
            try {
                listener.close();
            } catch (Throwable t) {
                logger.warn("shutdown listener invocation failed", t);
            }
        }
    }

    
}