Newsgroup: it.comp.java
Titolo: Annientare le finestre

Salva a tutti,
come si fa a scaricare dalla memoria grafica una finestra?
Mi spiego meglio: se io eseguo questo codice
   JFrame f = new JFrame("finestra 1");
   f.setVisible(true);
   f = new JFrame("finestra 2");
   f.setVisible(true);
vengono create due finestre, ma perdo ogni riferimento alla prima, che
rimane li sul desktop per conto suo. Io vorrei invece rimuovere dalla
memoria la prima, per tenermi solo la seconda.
Ho trovato il metodo f.removeNotify() che (almeno all'apparenza) fa
esattamente quello che vorrei, ma nella documentazione c'č scritto che č
fatto per essere usato dal toolkit internamente e non dai programmi.
Qualcuno sa dirmi cosa dovrei usare? Grazie!


l'area di mamoria che Java usa per allocare gli Ogetti si Chiama Java Heap,
per concezione Java non offere al programmatore la possibilità di
deallocare memoria in maniera esplicita, la Java Heap viene liberato da un
processo
che si chiama Garbage Collector che  libera  la memoria occupata dagli
oggetti non più referenziati, quindi il tuo compito e solo staccare tutti i
riferimenti al primo JFrame e
aspettare che il GC faccia il suo lavoro.

    f.setVisible(true);
Forse con f.dispose() PRIMA di instanziare la seconda JFrame?
Sono andato a naso leggendo la documentazione.
Il metodo viene ereditato nella classe JFrame da java.awt.Window
Spero sia quello che cerchi.
Guido.

 aspettare che il GC faccia il suo lavoro.
Conosco il garbage collector, e so cos'è l'heap. Infatti mi riferivo
precisamente alla memoria grafica.
Quando istanzi una finestra viene allocata della memoria nell'heap, che è
quella a cui ti riferisci tu, e viene allocata anche della memoria grafica,
che è quella visibile sullo schermo.
Avevo appunto scritto quelle quattro righe di esempio:
   JFrame f = new JFrame("finestra 1");
   f.setVisible(true);
   f = new JFrame("finestra 2");
   f.setVisible(true);
Alla seconda new JFrame perdi il riferimento alla prima finestra e la sua
allocazione nell'heap viene rilascita dal garbage collector, ma la finestra
rimane visibile, appunto perché rimane nella memoria grafica.

 Forse con f.dispose() PRIMA di instanziare la seconda JFrame?
In effetti era proprio quello ch cercavo. Una cosa però mi ha lasciato
perplesso:
se esegue il dispose di una finestra dovrei deallocarla dalla memoria, ma
dopo averlo fatto è comunque possibile accedere ai suoi metodi.
In pratica è possibile fare
  f.dispose();
  f.setVisible(true);
La stessa cosa succede con il metodo removeNotify(). Ma allora a cosa
servono?
O forse è il setVisible che si accorge che la finestra è stata deallocata e
la rialloca in memoria grafica?

   f.setVisible(true);
Ti riporto qui sotto la documentazione di java.awt.Window.dispose():
Releases all of the native screen resources used by this Window, its
subcomponents, and all of its owned children. That is, the resources
for these Components will be destroyed, any memory they consume
will be returned to the OS, and they will be marked as undisplayable.
/*Nota le frasi seguenti :*/
The Window and its subcomponents can be made displayable again by
rebuilding the native resources with a subsequent call to pack or show.
The states of the recreated Window and its subcomponents will be identical
to the states of these objects at the point where the Window was disposed
(not accounting for additional modifcations between those actions).
See Also:
Component.isDisplayable(), pack(), show()
Ora, io credo (ma potrebbe essere una stron*ata...) che con dispose vengano
rilasciate le risorse necessarie a *visualizzare* la JFrame, ma NON
l'oggetto
JFrame stesso (e da qui si spiegherebbe come mai lo stato resti invariato
dopo
dispose).
In altre parole, mentre passando da setVisible(true) a setVisible(false) si
mantiene
sia la memoria allocata per la visualizzazione che quella allocata per
l'oggetto JFrame,
con dispose mantieni solo la memoria relativa all'oggetto (e non quella
relativa alla vista).
Tutto questo con beneficio di inventario perchè sono solo supposizioni mie.
;)
Ciao.

 Ciao.
Convengo pienamente con le tue osservazioni o almeno, visto che non sono un
grande esperto, credo che siano giuste. A questo punto il mio problema si
complica, nel senso che per liberarsi effettivamente di un frame bisogna
fare una cosa del tipo:
  finestra.dispose();
  finestra = null;
Io vorrei fare entrambe le cose quando l'utente chiude la finestra. Per il
dispose non ci sono problemi, ma il finestra = null deve essere eseguito
dalla classe che ha come attributo l'istanza di finestra.
L'unico metodo che mi è venuto in mente è di impostare una flag ad un valore
preciso quando la finestra viene chiusa e, dalla classe esterna, continuare
a controllare la flag per deallocare l'istanza di finestra quando trovo quel
valore.
Non c'è un metodo più pratico? (ah già, grazie per la risposta :-))

 Non c'è un metodo più pratico? (ah già, grazie per la risposta :-))
Io credo che basti semplicemente riassegnare il riferimento "finestra"
ad un'altra istanza di JFrame. Così facendo il vecchio oggetto
JFrame (quello per il quale hai chiamato dispose) non è più
raggiungibile e diventa "cibo per il garbage collector". :)
E' sufficientemente semplice?
PS: fai una ricerchina su gùghol circa la pratica del "quoting" nei
newsgroups.

 raggiungibile e diventa "cibo per il garbage collector". :)
Beh, facendo una new torno esattamente al punto di prima.
Comunque, anche facendo una new, il problema non cambia.
finestra = new JFrame() dovrei farlo eseguirlo dalla classe che contiene
finestra; come faccio a capire da dentro questa casse che l'utente ha chiuso
la finestra?

 la finestra?
Devi mettere un ActionListener nella classe principale che intercetti
la chiusura della finestra. Poi gestisci l'evento come credi.
Per esempio, se nella classe principale tu volessi gestire la pressione
di un tasto quit:
1:Nella classe principale (chiamiamola ClientFrame), supponendo
che tu voglia intercettare la pressione di un JButton, metti:
...
//Si stanno creando i controlli in ClientFrame:
jQuitButton.addActionListener(new QuitListener());
...
2: In ClientFrame metti una inner class che implementa ActionListener:
 private class QuitListener implements ActionListener{
      public void actionPerformed(ActionEvent e) {
        //Si č premuto il tasto Quit
        //Fai quello che devi fare, ad esempio:
        System.out.println("Hai premuto Quit");
        ClientFrame.this.jQuitButton.setEnabled(false);
      }
  }
Quando si preme il bottone Quit viene eseguito il metodo actionPerformed
dell'ActionListener registrato per il bottone.
Puoi usare anche anonymous inner classes, ma la cosa migliore
č studiarsi un po' Swing & Company.
Se mi dicessi di piů sulla "semantica" della tua applicazione magari
potrei essere piů preciso.

 la chiusura della finestra. Poi gestisci l'evento come credi.
[cut]
Ho capito! Ero talmente abituato a gestire gli eventi degli oggetti grafici
tramite il designer visuale di jbuilder che non pensavo piů a gestirmi gli
ascoltatori!
Grazie grazie!