Java Swing dispose () vs setVisible (false)

J’ai une application Java autonome qui récupère les données d’une firebase database et les affiche dans une table JTable. Lorsque l’application démarre, l’utilisateur est invité à entrer un nom d’utilisateur / mot de passe dans un JDialog. Une fois que les informations d’identification correctes ont été entrées, la JFrame principale contenant les données est affichée. Sur le JFrame principal, j’ai un bouton de déconnexion qui, lorsque vous cliquez dessus, devrait fermer le JFrame principal et afficher à nouveau le login JDialog. Tout fonctionne généralement sauf que j’ai constaté que le cadre principal JFrame ne disparaissait pas lorsque l’utilisateur cliquait sur le bouton de déconnexion. Voici un petit exemple de travail de mon code:

Main.java:

import javax.swing.SwingUtilities; public class Main { public static void main(Ssortingng[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new MainFrame(); } }); } } 

MainFrame.java:

 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; public class MainFrame extends JFrame implements ActionListener { private JButton button; private MyDialog dialog; public MainFrame() { super("this is the JFrame"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); dialog = new MyDialog(this); button = new JButton("click me to hide this JFrame and display JDialog"); button.addActionListener(this); add(button); pack(); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { setVisible(false); // works when changed to dispose(); dialog.setVisible(true); } } 

MyDialog.java:

 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; public class MyDialog extends JDialog implements ActionListener { private JFrame parentFrame; private JButton button; public MyDialog(JFrame parentFrame) { super(parentFrame, "this is the JDialog", true); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); this.parentFrame = parentFrame; button = new JButton("click me to hide JDialog and show JFrame"); button.addActionListener(this); add(button); pack(); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { setVisible(false); parentFrame.setVisible(true); } } 

Dans MainFrame.java, si je modifie la ligne qui dit setVisible(false) pour dispose() alors JFrame disparaît lorsque je clique sur le bouton. Ma question est la suivante: pourquoi cela fonctionne-t-il avec dispose() et non avec setVisible(false) ? Existe-t-il un meilleur moyen pour moi d’organiser mon code? Je suis nouveau sur Swing, donc je m’excuse s’il s’agit d’une question fondamentale. Je vous remercie.


MODIFIÉ 2011-10-19 10:26 HAP

Merci à tous pour votre aide. J’ai changé le JDialog pour avoir un parent nul et maintenant tout fonctionne comme je le voulais.

Voir la ligne où vous initiez le JDialog:

 dialog = new MyDialog(this); 

Vous définissez le même cadre que le cadre parent sur lequel repose la boîte de dialog. Vous voyez, un dialog ne peut pas apparaître seul, il doit être placé au-dessus d’un cadre parent.

Donc dans votre code, quand vous écrivez:

 setVisible(false); // works when changed to dispose(); dialog.setVisible(true); 

Dans la première ligne, vous indiquez que le cadre doit disparaître, puis vous indiquez que la boîte de dialog apparaît, ce qui la fait apparaître sur son cadre parent. Comme le cadre parent est identique, il semble restr visible pour vous. Si vous supprimez la deuxième ligne, je suis sûr que le cadre disparaîtrait. Mais lorsque vous indiquez au cadre de se défaire, il disparaît complètement car vous lui avez dit non seulement de perdre de la visibilité, mais également de se retirer de la mémoire.

Ensuite, lorsque vous indiquez à la boîte de dialog qu’elle apparaît, elle recherche sa JFrame (qui a été supprimée), la réinitialise et l’ouvre.

Pour résoudre votre problème, vous devez créer un nouveau JFrame distinct pour JDialog. Ensuite, n’utilisez pas Dispos et utilisez simplement la commande setVisible.

-Asaf

Je vais simplement donner le code correct, dans mon propre style. Ce n’est certainement pas la meilleure solution, ni même celle qui a fait ses preuves.

setVisible (false) sur l’image principale doit appeler l’opération de fermeture, logiquement pour une image principale EXIT_ON_CLOSE. Si la boîte de dialog est un enfant du cadre principal, l’application se ferme.

J’ai donc fait de la boîte de dialog modale une deuxième fenêtre supérieure, qui a un parent (JFrame) null. Vous avez donc une application avec deux fenêtres supérieures. Et les dialogs modaux sont à chaque fois disposés. J’ai créé le dialog modal DO_NOTHING_ON_CLOSE, car vous ne voulez pas que l’icône Fermer fonctionne. D’où la dispose () dans l’actionPerformed. (Si vous avez à tout moment un parent, vous pouvez utiliser getOwner () au lieu de copier le parent dans un champ.)

 public class Main { public static void main(Ssortingng[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { MainFrame mainFrame = new MainFrame(); mainFrame.actionPerformed(null); } }); } } public class MainFrame extends JFrame implements ActionListener { private JButton button; public MainFrame() { super("this is the JFrame"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); button = new JButton("click me to hide this JFrame and display JDialog"); button.addActionListener(this); add(button); pack(); } @Override public void actionPerformed(ActionEvent e) { MyDialog dialog = new MyDialog(MainFrame.this); dialog.setVisible(true); setVisible(false); } } public class MyDialog extends JDialog implements ActionListener { private JButton button; private JFrame parentFrame; public MyDialog(JFrame parentFrame) { super((JFrame)null, "this is the JDialog", false); this.parentFrame = parentFrame; setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); button = new JButton("click me to hide JDialog and show JFrame"); button.addActionListener(this); add(button); pack(); setVisible(false); } @Override public void actionPerformed(ActionEvent e) { parentFrame.setVisible(true); dispose(); } }