2011-10-18 54 views
8

Tengo una aplicación Java independiente que obtiene datos de una base de datos y los muestra en una JTable. Cuando se inicia la aplicación, se le solicita al usuario un nombre de usuario/contraseña en un JDialog. Una vez que se ingresan las credenciales correctas, se visualiza el JFrame principal que contiene los datos. En el JFrame principal, tengo un botón de cerrar sesión que, al hacer clic, debe cerrar el JFrame principal y volver a mostrar el JDialog de inicio de sesión. Todo funciona principalmente, excepto que he encontrado que el JFrame principal no desaparece cuando se hace clic en el botón de cerrar sesión. A continuación se muestra un pequeño ejemplo de trabajo de mi código:Java Swing dispose() frente a setVisible (falso)

Main.java:

import javax.swing.SwingUtilities; 

public class Main { 

    public static void main(String[] 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); 
    } 
} 

En MainFrame.java si cambio la línea que dice setVisible(false) a dispose(), entonces el JFrame desaparece cuando hago clic en el botón. Mi pregunta es, ¿por qué funciona esto con dispose() y no con setVisible(false)? ¿Hay una mejor manera de organizar mi código? Soy nuevo en Swing, así que me disculpo si esta es una pregunta básica. Gracias.


EDITADO 2011-10-19 10:26 PDT

Gracias a todos por su ayuda. Cambié el JDialog para tener un padre nulo y ahora todo funciona como yo quería.

+0

Para una mejor ayuda antes, publique un [SSCCE] (http: // pscode. org/sscce.html). –

Respuesta

6

ver la línea donde se inicia la JDialog:

dialog = new MyDialog(this); 

está configurando el mismo marco que el marco principal de que el diálogo se sienta en. Verá, un diálogo no puede aparecer por sí solo, debe estar sobre un cuadro principal.

Así que en su código, cuando escribe:

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

En la primera línea le dice al marco a desaparecer, y luego le dice al diálogo que aparezca, lo que realmente dice el cuadro de diálogo que aparezca en su marco padre . Dado que el marco principal es el mismo, parece que permanece visible para usted. Si eliminas la segunda línea, estoy seguro de que el marco desaparecería. Pero cuando le dices al cuadro que se deshaga, desaparece por completo porque le dijiste no solo que pierda visibilidad, sino que también se retire de la memoria.

Luego, cuando le dice al cuadro de diálogo que aparezca, busca su JFrame (que ha sido desechado), lo reinicializa y abre.

La manera de resolver su problema es crear un nuevo JFrame separado para el JDialog. Entonces no use dispose y simplemente use el comando setVisible.

-Asaf

+1

Podría ser suficiente para no hacer que el marco vuelva a abrir su marco principal. Por lo tanto, realice la supercompetencia en 'MyDialog()' go: 'super (nulo," este es el JDialog ", falso);'. Si el cuadro principal está oculto, no recibirá una entrada significativa de todos modos, por lo que no hay motivo para que el diálogo sea modal. – millimoose

+0

@Inerdia Tiene razón, esa también es una opción. Olvidé que el booleano existe para la modalidad. Además, estoy bastante seguro de que la modalidad booleana ha quedado en desuso y ahora se prefiere el método ModalityType. – Asaf

+0

No realmente obsoleto, al menos no oficialmente. Se especifica qué valor booleano corresponde a qué tipo de modalidad, por lo que probablemente solo se trate de una cuestión de estilo que prefiera. – millimoose

0

simplemente daré código correcto, en mi propio estilo. Ciertamente no es la única o mejor solución probada.

setVisible (falso) en el marco principal debe invocar la operación de cierre, lógicamente para un marco principal EXIT_ON_CLOSE. Si el cuadro de diálogo es un elemento secundario del cuadro principal, entonces la aplicación se cierra.

Así que hice del cuadro de diálogo modal una segunda ventana superior, que tiene un nulo (JFrame) como primario. Por lo tanto, tiene una aplicación con dos ventanas superiores. Y los diálogos modales son eliminados cada vez. Hice el diálogo modal DO_NOTHING_ON_CLOSE, ya que no desea que el ícono Cerrar funcione. De ahí el desecho() en la acción realizada. (Si en cualquier momento tiene un padre, es posible utilizar getOwner() en lugar de copiar el padre a un campo.)

public class Main { 

    public static void main(String[] 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(); 
    } 
} 
+1

No creo que setVisible invoque la operación de cierre. Simplemente oculta el cuadro/diálogo ... – Bogdan