I learned Java for about 1 year some years ago. Now I wanted to go back to it, but my skills got a bit rusty. So I'm using Eclipse with the WindowBuilder to make an easy Form Application to get started again. I wanted to get a popup window when I exit the application because in future projects I need to execute some code when the application is being exited by another way than my own exit button (for example via the red cross or Alt+F4).
So this is my code so far:
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);
}
}
I used the code for the "when the Application is being exited" from this example, but no matter how I close it, no "Messagebox is appearing". When I use the code for the MessageBoxes directly after the main void, the MessageBoxes appear, so I guess I missplaced the ShutdownHook.
I would really appreciate if anybody can help me fix this problem.
I'm a little late to the party here but figured I'd add my 2 cents. I think it's best to use a static class that allows for shutdown listeners. It's much less complicated, and allows for checking if the JVM is currently shutting down (ex: to hide log messages). Here's the implementation I went with:
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);
}
}
}
}
The shutdown hook is meant to perform certain actions (such as closing database connections and shutting down threads) once the application has been shut down (be it by a System.exit
call or a kill signal from the OS). It is not meant to be used for these kinds of dialogs.
You will want to add a WindowListener
to your JFrame
, and perform an action on the windowClosing
and/or windowClosed
events. In this listener, you can then display a dialog or whatever you wish.
If you wish to be able to override the closing of the window, you can find details on how to do so on this question .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.