Comment programmer la fermeture d'un JFrame
Quelle est la bonne façon d'obtenir un JFrame
à fermer, comme si l'utilisateur avait appuyé sur le bouton X
fermer, ou appuyé sur Alt + F4 (sous Windows)?
j'ai mon opération de fermeture par défaut réglée comme je veux, via:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
C'est exactement ce que je veux avec les mêmes contrôles. Cette question n'est pas de cela.
ce que je veux vraiment faire est de faire en sorte que L'interface graphique se comporte de la même manière qu'une pression sur le bouton X
le ferait se comporter.
supposez que je devais étendre WindowAdaptor
et ensuite ajouter une instance de mon adaptateur comme un auditeur via addWindowListener()
. J'aimerais voir la même séquence d'appels par windowDeactivated()
, windowClosing()
, et windowClosed()
que celle qui se produirait avec le bouton de fermeture X
. Pas tant de briser la fenêtre que de lui dire de se déchirer, pour ainsi dire.
18 réponses
si vous voulez que l'interface graphique se comporte comme si vous aviez cliqué sur le bouton X
fermer, alors vous devez envoyer un événement de fermeture de fenêtre au Window
. Le ExitAction
de fermer une Application vous permet d'ajouter cette fonctionnalité à un élément de menu ou à tout composant qui utilise Action
facilement.
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object
pas trop délicat.
si par Alt-F4 ou X vous voulez dire" quitter L'Application immédiatement sans tenir compte de ce que D'autres fenêtres ou fils sont en cours d'exécution", alors System.exit(...)
fera exactement ce que vous voulez d'une manière très abrupte, brute-force, et peut-être problématique.
si par Alt-F4 ou X vous voulez dire cacher la fenêtre, alors frame.setVisible(false)
est la façon dont vous" fermez " la fenêtre. La fenêtre va continuer à consommer des ressources/mémoire mais peut être rendue visible à nouveau très rapidement.
si par Alt-F4 ou X vous voulez dire cacher la fenêtre et disposer de toutes les ressources qu'elle consomme, alors frame.dispose()
est la façon dont vous" fermez " la fenêtre. Si le cadre était la dernière fenêtre visible et qu'il n'y a pas d'autres threads Non-démon en cours d'exécution, le programme se terminera. Si vous affichez la fenêtre à nouveau, elle devra réinitialiser toutes les ressources natives (tampon graphique, poignées de fenêtre, etc.).
dispose()
pourrait être plus proche du comportement que vous voulez vraiment. Si votre application a plusieurs fenêtres ouvertes, voulez-vous Alt-F4 ou X pour quitter l'application ou juste fermer la fenêtre active?
le tutoriel Java Swing sur les écouteurs de fenêtre peut vous aider à clarifier les choses pour vous.
Si vous avez fait cela pour s'assurer que l'utilisateur ne peut pas fermer la fenêtre:
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
alors vous devez changer votre pullThePlug()
méthode pour être
public void pullThePlug() {
// this will make sure WindowListener.windowClosing() et al. will be called.
WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
// this will hide and dispose the frame, so that the application quits by
// itself if there is nothing else around.
setVisible(false);
dispose();
// if you have other similar frames around, you should dispose them, too.
// finally, call this to really exit.
// i/o libraries such as WiiRemoteJ need this.
// also, this is what swing does for JFrame.EXIT_ON_CLOSE
System.exit(0);
}
j'ai trouvé que c'était la seule façon qui joue bien avec le WindowListener
et JFrame.DO_NOTHING_ON_CLOSE
.
quitter le processus D'exécution Java est très facile, fondamentalement, vous devez faire juste deux choses simples:
- Appel de méthode java
System.exit(...)
à l'application du point de quitter. Par exemple, si votre application est basée sur un cadre, vous pouvez ajouter l'auditeurWindowAdapter
et appelerSystem.exit(...)
dans sa méthodewindowClosing(WindowEvent e)
.
Note: vous devez appeler System.exit(...)
sinon votre programme est une erreur.
- éviter les exceptions java inattendues pour s'assurer que la méthode exit peut être appelée toujours.
Si vous ajoutez
System.exit(...)
au bon moment, mais cela ne signifie pas que la méthode peut être appelée toujours, parce que des exceptions java inattendues peuvent empêcher la méthode d'être appelée.
ceci est fortement lié à vos compétences en programmation.
** voici un exemple plus simple ( JFrame
) qui vous montre comment appeler méthode de sortie
import java.awt.event.*;
import javax.swing.*;
public class ExitApp extends JFrame
{
public ExitApp()
{
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
dispose();
System.exit(0); //calling the method is a must
}
});
}
public static void main(String[] args)
{
ExitApp app=new ExitApp();
app.setBounds(133,100,532,400);
app.setVisible(true);
}
}
voici vos options:
System.exit(0); // stop program
frame.dispose(); // close window
frame.setVisible(false); // hide window
non seulement pour fermer le JFrame mais aussi pour déclencher des événements WindowListener, essayez ceci:
myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
ferme non seulement la cellule, mais aussi l'ensemble de l'application, d'où "EXIT ON CLOSE"
pour obtenir le même résultat, vous devez effectivement quitter l'application, pour cela simplement appeler
System.exit(0);
L'effet est exactement le même.
la meilleure façon de fermer un cadre oscillant de façon programmatique est de le faire se comporter comme il le ferait lorsque le bouton" X " est appuyé. Pour ce faire, vous devrez implémenter WindowAdapter qui convient à vos besoins et définir l'opération de fermeture par défaut de frame pour ne rien faire (DO_NOTHING_ON_CLOSE).
initialisez votre image comme ceci:
private WindowAdapter windowAdapter = null;
private void initFrame() {
this.windowAdapter = new WindowAdapter() {
// WINDOW_CLOSING event handler
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
// You can still stop closing if you want to
int res = JOptionPane.showConfirmDialog(ClosableFrame.this, "Are you sure you want to close?", "Close?", JOptionPane.YES_NO_OPTION);
if ( res == 0 ) {
// dispose method issues the WINDOW_CLOSED event
ClosableFrame.this.dispose();
}
}
// WINDOW_CLOSED event handler
@Override
public void windowClosed(WindowEvent e) {
super.windowClosed(e);
// Close application if you want to with System.exit(0)
// but don't forget to dispose of all resources
// like child frames, threads, ...
// System.exit(0);
}
};
// when you press "X" the WINDOW_CLOSING event is called but that is it
// nothing else happens
this.setDefaultCloseOperation(ClosableFrame.DO_NOTHING_ON_CLOSE);
// don't forget this
this.addWindowListener(this.windowAdapter);
}
vous pouvez fermer le cadre programmatiquement en lui envoyant L'événement WINDOW_CLOSING, comme ceci:
WindowEvent closingEvent = new WindowEvent(targetFrame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEvent);
cela fermera le cadre comme le bouton" X " a été pressé.
cet exemple montre comment réaliser l'opération confirmée de fermeture de fenêtre.
la fenêtre a un adaptateur de fenêtre qui commute l'opération de fermeture par défaut à EXIT_ON_CLOSE
ou DO_NOTHING_ON_CLOSE
dépendant de votre réponse dans le OptionDialog
.
la méthode closeWindow
de la ConfirmedCloseWindow
déclenche un événement de fermeture de fenêtre et peut être utilisée n'importe où i.e. comme action d'un élément de menu
public class WindowConfirmedCloseAdapter extends WindowAdapter {
public void windowClosing(WindowEvent e) {
Object options[] = {"Yes", "No"};
int close = JOptionPane.showOptionDialog(e.getComponent(),
"Really want to close this application?\n", "Attention",
JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null,
options,
null);
if(close == JOptionPane.YES_OPTION) {
((JFrame)e.getSource()).setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
} else {
((JFrame)e.getSource()).setDefaultCloseOperation(
JFrame.DO_NOTHING_ON_CLOSE);
}
}
}
public class ConfirmedCloseWindow extends JFrame {
public ConfirmedCloseWindow() {
addWindowListener(new WindowConfirmedCloseAdapter());
}
private void closeWindow() {
processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
}
basé sur les réponses déjà fournies ici, c'est la façon dont je l'ai mis en œuvre:
JFrame frame= new JFrame()
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame stuffs here ...
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
le JFrame permet à l'événement de se fermer et à la fermeture, sort.
si vous ne voulez vraiment pas que votre application se termine quand un JFrame est fermé alors,
utilisation: setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
au lieu de: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
voici un résumé de ce à quoi ressemble la solution,
myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
Cette réponse a été donnée par Alex et je voudrais le recommander. Ça a marché pour moi et autre chose, c'est simple et si simple.
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object
vous devez insérer l'appel dans la file D'attente de messages AWT pour que tout le timing se passe correctement, sinon il ne va pas envoyer la séquence d'événements correcte, en particulier dans un programme multi-threadé. Lorsque cela est fait, vous pouvez gérer la séquence d'événements résultante exactement comme vous le feriez si l'Utilisateur a cliqué sur le bouton [x] pour un JFrame décoré avec OS.
public void closeWindow()
{
if(awtWindow_ != null) {
EventQueue.invokeLater(new Runnable() {
public void run() {
awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
}
});
}
}
affichant ce qui était dans le corps des questions comme réponse de CW.
a voulu partager les résultats, principalement dérivés du lien de camickr. Fondamentalement, je dois jeter un WindowEvent.WINDOW_CLOSING
à la file d'attente d'événements de l'application. Voici un résumé de ce à quoi ressemble la solution
// closing down the window makes sense as a method, so here are
// the salient parts of what happens with the JFrame extending class ..
public class FooWindow extends JFrame {
public FooWindow() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(5, 5, 400, 300); // yeah yeah, this is an example ;P
setVisible(true);
}
public void pullThePlug() {
WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
}
}
// Here's how that would be employed from elsewhere -
// someplace the window gets created ..
FooWindow fooey = new FooWindow();
...
// and someplace else, you can close it thusly
fooey.pullThePlug();
si vous ne voulez pas que votre application se termine quand un JFrame est fermé, utiliser: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)
au lieu de: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
de la documentation:
DO_NOTHING_ON_CLOSE (defined in WindowConstants)
: ne rien faire; exiger le programme pour gérer l'opération dans la méthode windowClosing d'un objet WindowListener enregistré.
HIDE_ON_CLOSE (defined in WindowConstants)
: Masquer automatiquement le cadre après avoir invoqué tout objet WindowListener enregistré.
DISPOSE_ON_CLOSE (defined in WindowConstants)
: cacher et disposer automatiquement le cadre après avoir invoqué des objets WindowListener enregistrés.
EXIT_ON_CLOSE (defined in JFrame)
: Sortir de l'application en utilisant le Système de sortie de la méthode. Utilisez ceci seulement dans les applications.
pourrait encore être utile:
Vous pouvez utiliser setVisible(false)
sur votre JFrame si vous voulez afficher le même cadre encore.
Sinon, appelez dispose()
pour supprimer toutes les ressources d'écran natives.
copié de Peter Lang
j'ai essayé ceci, écrivez votre propre code pour l'événement formWindowClosing () .
private void formWindowClosing(java.awt.event.WindowEvent evt) {
int selectedOption = JOptionPane.showConfirmDialog(null,
"Do you want to exit?",
"FrameToClose",
JOptionPane.YES_NO_OPTION);
if (selectedOption == JOptionPane.YES_OPTION) {
setVisible(false);
dispose();
} else {
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
}
}
cela demande à l'utilisateur s'il veut sortir du cadre ou de l'Application.