PDA

View Full Version : [JAVA] pulsante che non chiude


tatothejoker
06-11-2006, 18:35
ciao a tutti qualcuno mi sa dire cosa non funziona in questo codice?
il pulsante "chiudi" dovrebbe far chiudere la finestra ma non va

grazie a tutti
joker

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import java.awt.event.*;


public class Credits

{

public void visualizza ()
{
//creo il pannello che conterrà i JLabel
JPanel credits = new JPanel();

//creo i contenuti del JPanel

//inserisco il logo
JLabel logo = new JLabel(new ImageIcon ("img/logo.gif"));

//i testi
JLabel testo = new JLabel ("x");
JLabel testo1 = new JLabel ("x");
JLabel testo2 = new JLabel ("x");
JLabel testo3 = new JLabel ("x");
JLabel testo4 = new JLabel ("x");
JLabel testo5 = new JLabel ("x");
JLabel testo6 = new JLabel ("x");

//il pulsante per chiudere la finestra
final JButton chiudi = new JButton("> chiudi <");


//inserisco il logo del corso di laurea
credits.add(logo);

//inserisco le JLabel con i testi
credits.add(testo);
credits.add(testo1);
credits.add(testo2);
credits.add(testo3);
credits.add(testo4);
credits.add(testo5);
credits.add(testo6);

//chiudi = new JButton( "> chiudi <" );
credits.add(chiudi);

//creo il JFrame che conterrà i miei oggetti
final JFrame finestraCredits = new JFrame();
//da la possibilità al Frame di essere chiuso
finestraCredits.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//titolo della finestra
finestraCredits.setTitle("Credits");
//dimensioni della finestra (x,y)
finestraCredits.setSize(410,330);
//aggiungo il pannello alla finestra
finestraCredits.setContentPane(credits);
//rendo ridimensionabile la finestra
finestraCredits.setResizable(false);
//rendo visibile la finestra
finestraCredits.setVisible(true);


//creo il listener per catturi il click del mouse sul pulsante chiudi
chiudi.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
finestraCredits.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
);

}

}

redcloud
06-11-2006, 19:45
ciao a tutti qualcuno mi sa dire cosa non funziona in questo codice?
il pulsante "chiudi" dovrebbe far chiudere la finestra ma non va

grazie a tutti
joker

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import java.awt.event.*;


public class Credits

{

public void visualizza ()
{
//creo il pannello che conterrà i JLabel
JPanel credits = new JPanel();

//creo i contenuti del JPanel

//inserisco il logo
JLabel logo = new JLabel(new ImageIcon ("img/logo.gif"));

//i testi
JLabel testo = new JLabel ("x");
JLabel testo1 = new JLabel ("x");
JLabel testo2 = new JLabel ("x");
JLabel testo3 = new JLabel ("x");
JLabel testo4 = new JLabel ("x");
JLabel testo5 = new JLabel ("x");
JLabel testo6 = new JLabel ("x");

//il pulsante per chiudere la finestra
final JButton chiudi = new JButton("> chiudi <");


//inserisco il logo del corso di laurea
credits.add(logo);

//inserisco le JLabel con i testi
credits.add(testo);
credits.add(testo1);
credits.add(testo2);
credits.add(testo3);
credits.add(testo4);
credits.add(testo5);
credits.add(testo6);

//chiudi = new JButton( "> chiudi <" );
credits.add(chiudi);

//creo il JFrame che conterrà i miei oggetti
final JFrame finestraCredits = new JFrame();
//da la possibilità al Frame di essere chiuso
finestraCredits.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//titolo della finestra
finestraCredits.setTitle("Credits");
//dimensioni della finestra (x,y)
finestraCredits.setSize(410,330);
//aggiungo il pannello alla finestra
finestraCredits.setContentPane(credits);
//rendo ridimensionabile la finestra
finestraCredits.setResizable(false);
//rendo visibile la finestra
finestraCredits.setVisible(true);


//creo il listener per catturi il click del mouse sul pulsante chiudi
chiudi.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
System.exit(0);
}
}
);

}

}

Modifiche in GRASSETTO

DISPOSE_ON_CLOSE nasconde solamente la finestra, non la dealloca (ma con System.exit(0) si dealloca in ogni caso).

PGI-Bis
06-11-2006, 22:02
System.exit(0) corrisponde a:

"Ammazza la macchina virtuale Java".

Nell'actionPerformed ci va:

finestra.dispose();

Idem per la linea:

finestraCredits.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

deve essere:

finestraCredits.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

Prima non andava perchè ciò che capitava alla pressione del pulsante chiudi era una mutazione del comportamento della finestra alla pressione del pulsante con la X in alto a destra (e omologhi).

Non chiudevi la finestra ma le dicevi "ok ciccia, da adesso in poi quando ti premono la X tu dispose()".

redcloud
06-11-2006, 22:16
Beh si ho dato per scontato che volesse chiudere l'applicazione. Comunque se non sbaglio dispose non dealloca la memoria. Per esempio ho aperto delle JDialog da un JFrame e la memoria occupata è aumentata di alcuni MB. Quando ho "disposato" le JDialog, la memoria occupata non si è liberata...

PGI-Bis
06-11-2006, 22:50
dispose() non libera la memoria ma candida le risorse occupate da quella finestra ad essere liberate. Ciò che fa immediatamente è escludere la finestra dal conto delle finestre visualizzabili. La cosa è rilevante perchè il Thread AWT Event Dispatcher, quello usato da Swing-AWT per propagare gli eventi UI, termina quando non ci siano più finestre visualizzabili.

Le sorti dell'AWT Event Dispatcher interessano soprattutto alla macchina virtuale Java. Quando il conto dei thread non demoni in una jvm diventa zero, la macchina virtuale si spegne (c.d. spegnimento dolce).

L'AWT Event Dispatcher è un Thread non demone dunque finchè c'è almeno una finestra visualizzabile (anche se non visibile) la JVM non può fermarsi da sola.

Il problema del System.exit sta nel fatto che per poterlo usare devi anche essere in grado di garantire che la tua applicazione sia l'unica che sta girando su quella JVM. E' rischioso ma facile e conveniente, far girare più di un'applicazione sulla stessa JVM perchè in tal modo più applicazione beneficiano dell'unica compilazione del JIT e condividono quell'overhead di memoria che ogni JVM prende per sè sola. Se di due applicazioni, sulla stessa JVM, una "System.exit" ci lascia le penne anche l'altra.

Più in generale, un System.exit è fatale per ogni Thread della stessa JVM, a prescindere dal fatto che siano o non siano demoni.

Per quanto riguarda il caso della memoria occupata e mai liberata occorre tener conto, credo, che la filosofia del garbage collector della JVM di Sun è: non liberare mai la memoria occupata. Lo fa perchè la maggior parte delle allocazioni sono automatiche (come per le variabili automatiche di C e C++) anche se l'allocazione avvenga sull'heap. Il resto è più conveniente liberarlo a blocchi e, al limite, una volta per tutte una volta che lo spazio disponibile sia insufficiente a nuove allocazioni.

Insomma, il gc è un bel furbone.