2016-01-12 15 views
6

La differenza che vedo è (in esecuzione su JDK 1.7):Perché gli ascoltatori di finestre/componenti sono richiamati in modo diverso quando setVisible (false) e dispose() sono chiamati?

setVisible(false), invoca componentHidden ma nonwindowClosed (stati l'API solo su dispose() quindi è OK anche se mi irrita)

ma

dispose(), invoca windowClosed ma noncomponentHidden

breve esempio l'esecuzione di codice (MCVE):

public class JDialogTest extends JDialog { 
    private static final long serialVersionUID = 1L; 

    public JDialogTest(JFrame owner){ 
     super(owner,ModalityType.APPLICATION_MODAL); 
     init(); 
    } 
    private void init() { 
     this.getContentPane().setLayout(new GridLayout(1,2)); 
     JButton btnVisible = new JButton("Set visible false"); 
     btnVisible.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       JDialogTest.this.setVisible(false); 
      } 
     }); 
     JButton btnDispose = new JButton("Dispose"); 
     btnDispose.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       JDialogTest.this.dispose(); 
      } 
     }); 
     this.getContentPane().add(btnVisible); 
     this.getContentPane().add(btnDispose); 
     this.pack(); 
    } 

    public static void main(String[] args) { 

     //A fake frame to test JDialog 
     JFrame fakeFrame = new JFrame("Fake Frame"); 
     fakeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     fakeFrame.getContentPane().setLayout(new BorderLayout()); 
     JButton btnOpen = new JButton("Open Dialog"); 
     fakeFrame.getContentPane().add(btnOpen,BorderLayout.CENTER); 
     fakeFrame.pack(); 
     fakeFrame.setLocationRelativeTo(null); 

     //Generate the test dialog 
     final JDialogTest dialog = new JDialogTest(fakeFrame); 
     dialog.addComponentListener(new ComponentAdapter() { 

      @Override 
      public void componentShown(ComponentEvent e) { 
       System.out.println("Component Shown"); 
      } 
      @Override 
      public void componentHidden(ComponentEvent e) { 
       System.out.println("Component Hidden"); 
      } 
     }); 

     dialog.addWindowListener(new WindowAdapter() { 
      @Override 
      public void windowOpened(WindowEvent e) { 
       System.out.println("Window open"); 
      } 
      @Override 
      public void windowClosed(WindowEvent e) { 
       System.out.println("Window closed"); 
      } 
     }); 
     dialog.setLocationRelativeTo(null); 

     btnOpen.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       dialog.setVisible(true); 
      } 
     }); 
     fakeFrame.setVisible(true); 
    } 
} 

NOTA: L'esempio dispone di un JDialog, ma vedo stesso comportamento in JFrame, per testare semplice collegare il ascoltatori allo fakeFrame e aggiungi pulsanti simili. (evitato in MVCE di mantenerlo M inimo)).

ho considerato questo post:

JDialog setVisible(false) vs dispose()

  • Nel risposte sembra che sia dovrebbe essere alcuna differenza, utilizzare dispose() ...

documentazione API:

Window.setVisible(boolean b) , Window.dispose(), ComponentListener.componentHidden(ComponentEvent e), WindowListener.windowClosed(WindowEvent e)

Perché mi interessa: Naturalmente per curiosità, ma anche perché io uso i tasti per chiudere la finestra (invocando dispose()) e l'interfaccia può essere chiuso dalla finestra vicino icona in alto/a destra e alt + F4 (invocando setVisible(false)!?). Quindi nessuno dei suddetti ascoltatori può essere usato. Solo lo HierarchyListener li catturerà entrambi e questo sembra contro-intuitivo.

MODIFICA: La domanda è intesa come "perché è così"? Qual è lo scopo?". Mi aspettavo dispose() per invocare sia! Non riesco a trovare alcun indizio nella documentazione delle API per il motivo per cui non.

+0

@mKorbel, modifica i tag poiché vedo lo stesso comportamento in JFrame. Ho visto lì dove alcuni commenti cancellati quando sono tornato da pranzo, qualcosa di interessante? –

+0

Perché sono metodi diversi e questo è ciò che il codice sorgente mostra. Cosa ti aspettavi? Che tipo di risposta stai cercando? – user1803551

+0

Ho aggiornato il post per riflettere ciò che mi aspettavo e quale risposta stavo saltando per ottenere. –

risposta

4

l'interfaccia può anche essere vicino in alto/a destra della finestra vicino icona alt + F4 (invocando setVisible (false) !?)

Ciò è determinato dal l'operazione di chiusura di default. è possibile impostare con setDefaultCloseOperation. l'impostazione predefinita è HIDE_ON_CLOSE, motivo per cui si ottiene un invocazione componentHidden .Se lo si imposta su DISPOSE_ON_CLOSE, si otterrà invece una chiamata windowClosed. L'impostazione su quest'ultimo ti consentirà di registrarti solo per questi tipi di eventi.

Indipendentemente da ciò, nascondere e smaltire fa cose diverse. Smaltire rilascia le risorse utilizzate mentre si nasconde no. Inoltre, nascondendo l'ultima finestra non uscirà dalla JVM mentre lo smaltirà.

Per quanto riguarda il lato tecnico del dispiegamento di eventi, ci sono molte intricatezze. Mentre lo smaltimento della finestra chiama il suo metodo di occultamento, l'invio degli eventi viene eseguito al termine delle operazioni. Ciò significa che l'EDT può inviare eventi "dopo il fatto". Poiché la finestra è chiusa, non invia l'evento di occultamento.

+0

Grazie per la tua risposta, sì, stavo ignorando il DISPOSE_ON_CLOSE sul JDialog cambierei il comportamento, quindi, naturalmente, se uso il pulsante con dispose, I ** deve impostarlo come operazione di chiusura predefinita **. Questo risolve la mia frustrazione .. ma i nostri cari sviluppatori di Oracle avrebbero potuto lanciare un bel componente nascosto prima della loro "complessità" –

+0

@PetterFriberg, prego. Non penso che l'eliminazione di una finestra debba attivare un 'componentHidden' perché una finestra dismessa non è nascosta, non esiste per così dire. Nascosto implica che esiste, solo non mostrato. – user1803551

+0

Anche come ogni chiamata a 'hide' invia un evento' componentHidden' così non tutte le chiamate a 'requestFocusInWindow' inviano un evento' focusGained', come indicato nell'API: "* Gli sviluppatori non devono mai presumere che questo componente è il proprietario del focus finché questo componente non riceve un evento FOCUS_GAINED. * ". – user1803551