2011-10-18 41 views
8

Possiedo un'applicazione Java autonoma che recupera i dati da un database e li visualizza in una tabella J. All'avvio dell'applicazione, all'utente viene richiesto un nome utente/password in un JDialog. Una volta inserite le credenziali corrette, viene visualizzato il JFrame principale contenente i dati. Sul JFrame principale ho un pulsante di disconnessione che, quando si fa clic, dovrebbe chiudere il JFrame principale e visualizzare di nuovo il JDialog di accesso. Tutto funziona per lo più tranne che ho scoperto che il JFrame principale non scompare quando si fa clic sul pulsante di disconnessione. Di seguito è riportato un piccolo esempio di lavoro del mio codice:Java Swing dispose() vs. setVisible (false)

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); 
    } 
} 

In MainFrame.java se cambio la linea che dice setVisible(false)-dispose() poi il JFrame va via quando clicco il bottone. La mia domanda è: perché funziona con dispose() e non con setVisible(false)? C'è un modo migliore per organizzare il mio codice? Sono nuovo di Swing quindi mi scuso se questa è una domanda di base. Grazie.


CURA 2011-10-19 10:26 PDT

Grazie a tutti per il vostro aiuto. Ho cambiato il JDialog per avere un genitore nullo e ora tutto funziona come volevo.

+0

Per una migliore aiuto prima, inviare un [SSCCE] (http: // pscode. org/sscce.html). –

risposta

6

vedere la linea in cui si avvia la JDialog:

dialog = new MyDialog(this); 

Si sta impostando lo stesso telaio come il frame principale che la finestra di dialogo si trova su. Vedete, una finestra di dialogo non può apparire da sola, deve stare in cima a una cornice genitore.

Quindi, nel codice, quando si scrive:

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

Nella prima riga si dice il telaio a scomparire, allora dite la finestra di dialogo a comparire, che racconta davvero la finestra di apparire sul suo frame principale . Dal momento che il frame principale è lo stesso, sembra che resti visibile a te. Se rimuovi la seconda riga, sono sicuro che il fotogramma scomparirà. Ma quando dici che la cornice deve essere eliminata, scompare del tutto perché hai detto non solo di perdere visibilità, ma anche di rimuoverla dalla memoria.

Poi, quando si dice la finestra di dialogo di apparire sembra per la sua JFrame (che sia stata ceduta), re-inizializza e si apre.

Il modo per risolvere il problema è creare un nuovo JFrame separato per JDialog. Quindi non usare dispose e basta usare il comando setVisible.

-Asaf

+1

Potrebbe essere sufficiente non rendere il frame che riapre il frame principale. Quindi, effettua la super chiamata in 'MyDialog()' go: 'super (null," questo è il JDialog ", false);'. Se il frame principale è nascosto, non riceverà comunque input significativi, quindi non c'è motivo di rendere il dialogo modale. – millimoose

+0

@Inerdia Sei corretto, anche questa è un'opzione. Ho dimenticato che il booleano esiste per le modalità. Inoltre, sono abbastanza sicuro che la modalità booleana sia stata deprecata e che ora sia preferito il metodo ModalityType. – Asaf

+0

Non proprio deprecato, almeno non ufficialmente. È specificato quale valore booleano corrisponde al tipo di modalità, quindi è probabilmente solo una questione di stile che preferisci. – millimoose

0

mi limiterò a dare codice corretto, nel mio stile. Certamente non è la soluzione migliore, se non addirittura la migliore.

setVisible (false) sul frame principale deve richiamare l'operazione di chiusura, logicamente per un frame principale EXIT_ON_CLOSE. Se la finestra di dialogo è figlia del frame principale, l'applicazione si chiude.

Così ho creato la finestra di dialogo modale una seconda finestra in alto, che ha un (JFrame) null come genitore. Quindi hai un'applicazione con due finestre in alto. E i dialoghi modali sono sempre disposti. Ho creato la finestra di dialogo modale DO_NOTHING_ON_CLOSE, perché non vuoi che l'icona Chiudi funzioni. Quindi il dispose() nell'azionePerformato. (Se in qualsiasi momento avere un genitore, è possibile utilizzare getOwner() invece di copiare il genitore 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

Non penso che setVisible invochi l'operazione di chiusura. Nasconde semplicemente la cornice/il dialogo ... – Bogdan