Professional Documents
Culture Documents
Premessa
Una finestra top level (di massimo livello) una finestra dotata di barra del titolo e bordi e
non contenuta in altre finestre. Ogni applicazione ha bisogno di una finestra di questo
tipo che funga da contenitore per tutti gli altri componenti dellinterfaccia utente.
La dispensa mostra alcuni metodi alternativi per creare una finestra top level mediante
scrittura diretta del codice e utilizzando il tool visuale Window Builder (integrato in Eclipse
LUNA). In particolare si vedr come creare una finestra con titolo, icona personalizzata e
centrata nello schermo del computer.
Indice
Gerarchia di classi coinvolte
Costruttori della classe JFrame
Propriet basilari di una finestra top level
Creazione di una finestra top level nel main
Creazione di una classe che definisce una finestra top level
Una variante: il metodo initialize
Posizionamento di una finestra e icona personalizzata: la classe Toolkit
Altre propriet di una finestra top level
Il problema dei metodi non thread safe
Creazione di una finestra top level con Window Builder
Videolezioni
Java Swing Creare finestre top level Parte 1
Java Swing Creare finestre top level Parte 2
Java Swing Creare finestre top level Parte 3
Java Swing Creare finestre top level Parte 4
Bocchi Cinzia
10/01/2015
La figura 1 mostra le principali classi coinvolte nella creazione di una finestra top level.
Una finestra top level viene creata come istanza della classe JFrame. Vediamo, allora,
alcuni costruttori di tale classe.
Bocchi Cinzia
10/01/2015
Metodo
public void setTitle(String title)
Imposta il titolo del frame alla stringa passata come parametro. Il titolo
pu essere impostato anche in fase di creazione dellistanza con il
costruttore JFrame(String title).
java.awt.Window
java.awt.Window
java.awt.Window
Bocchi Cinzia
10/01/2015
import javax.swing.JFrame;
public class MyFrame {
public static void main(String[] args) {
final
final
final
final
int
int
int
int
WIDTH = 450;
HEIGHT = 300;
X = 100;
Y = 100;
Bocchi Cinzia
10/01/2015
righi 07-10
Costanti simboliche che contengono rispettivamente i valori interi della larghezza e
dellaltezza della finestra, dellascissa e dellordinata del suo vertice superiore sinistro.
rigo 13
Crea una finestra top level come istanza della classe JFrame e le assegna il titolo
MyFrame.
rigo 16
Imposta la larghezza della finestra a WIDTH pixel e laltezza a HEIGHT pixel.
rigo 19
Posiziona il vertice superiore sinistro della finestra nel punto di coordinate (X, Y).
rigo 23
Associa al pulsante di chiusura della finestra loperazione che termina lapplicazione.
rigo 26
Visualizza la finestra.
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class MyFrame extends JFrame {
Bocchi Cinzia
public
public
public
public
static
static
static
static
final
final
final
final
int
int
int
int
WIDTH = 450;
HEIGHT = 300;
X = 100;
Y = 100;
public MyFrame() {
//Impostare il titolo della finestra
setTitle("MyFrame");
/*In alternativa
* super("MyFrame");
*/
//Impostare la dimensione della finestra
setSize(WIDTH, HEIGHT);
//Impostare la posizione iniziale
10/01/2015
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
setLocation(X, Y);
/*In alternativa a setSize + setLocation
* setBounds(X, Y, WIDTH, HEIGHT);
*/
//Impostare l'operazione associata al pulsante di chiusura
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
MyFrame frame = new MyFrame();
frame.setVisible(true);
}
}
MyFrame versione 2
rigo 03
Sopprime il warning riferito alla mancata serializzazione. La serializzazione utilizzata per
gli oggetti persistenti o in altre situazioni che, al momento, non ci interessano.
righi 06-09
Le costanti di classe WIDTH, HEIGHT, X e Y rappresentano rispettivamente la larghezza e
laltezza del frame e le coordinate del suo vertice superiore sinistro.
righi 13-18
Il costruttore della classe MyFrame esegue una chiamata al metodo setTitle per
impostare il titolo della finestra. In alternativa, possibile chiamare il costruttore della
superclasse JFrame, specificando come parametro il titolo del frame, utilizzando:
super("MyFrame").
rigo 21
Il metodo setSize imposta la dimensione del frame.
rigo 24
Il metodo setLocation imposta la posizione iniziale del frame; la posizione, se non
specificata, coincide con il punto origine degli assi.
rigo 27
Al posto dei metodi setSize e setLocation si pu usare il metodo setBounds: esso
effettua le due operazioni contemporaneamente.
rigo 31
La chiamata al metodo setDefaultCloseOperation imposta loperazione associata al
pulsante di chiusura del frame.
righi 35-37
Bocchi Cinzia
10/01/2015
Tra i metodi della classe presente il metodo main: in tal modo possibile testare il
funzionamento della classe, senza dover scrivere una specifica applicazione. Qualora si
scriva invece, un'applicazione che utilizza la classe MyFrame, il metodo main presente
nell'applicazione, prevarr su quello definito nella classe stessa.
Una volta creata la finestra, questa non ancora visibile. Per visualizzarla occorre
chiamare il metodo setVisible, passandogli come parametro true. La visualizzazione di
una finestra deve avvenire dopo che tutte le impostazioni iniziali sono state applicate.
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class MyFrame extends JFrame {
Bocchi Cinzia
public
public
public
public
static
static
static
static
final
final
final
final
int
int
int
int
WIDTH = 450;
HEIGHT = 300;
X = 100;
Y = 100;
public MyFrame() {
initialize();
}
private void initialize() {
//Impostare il titolo della finestra
setTitle("MyFrame");
//Impostare la dimensione della finestra
setSize(WIDTH, HEIGHT);
//Impostare la posizione iniziale
setLocation(X, Y);
//Impostare l'operazione associata al pulsante di chiusura
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
MyFrame frame = new MyFrame();
frame.setVisible(true);
}
10/01/2015
35
36
}
MyFrame versione 3
Bocchi Cinzia
10/01/2015
setIconImage(img);
Il metodo setIconImage, infine, imposta limmagine come icona della finestra.
Vediamo il codice completo.
Bocchi Cinzia
10/01/2015
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import
import
import
import
java.awt.Dimension;
java.awt.Image;
java.awt.Toolkit;
javax.swing.JFrame;
@SuppressWarnings("serial")
public class MyFrame extends JFrame {
public static final int WIDTH = 450;
public static final int HEIGHT = 300;
public MyFrame() {
initialize();
}
private void initialize() {
//Impostare il titolo della finestra
setTitle("MyFrame");
//Impostare la dimensione della finestra
setSize(WIDTH, HEIGHT);
//Impostare la posizione iniziale centrata nello schermo
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
int x = (screenWidth - WIDTH) / 2;
int y = (screenHeight - HEIGHT) / 2;
setLocation(x, y);
//Aggiungere un'icona personalizzata alla finestra
Image img =
kit.getImage(getClass().getResource("duke_icon.jpg"));
setIconImage(img);
//Impostare l'operazione associata al pulsante di chiusura
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
MyFrame frame = new MyFrame();
frame.setVisible(true);
}
}
MyFrame versione 4
Bocchi Cinzia
10/01/2015
10
Metodo
Bocchi Cinzia
10/01/2015
11
java.awt.Window
java.awt.Window
java.awt.Window
java.awt.Window
java.awt.Window
java.awt.Window
java.awt.Window
java.awt.Window
java.awt.Frame
java.awt.Frame
java.awt.Frame
java.awt.Frame
Bocchi Cinzia
10/01/2015
12
java.awt.JFrame
java.awt.JFrame
java.awt.JFrame
10/01/2015
13
metodo setVisible o pack per visualizzarla. Di solito, il metodo main, a questo punto,
termina e il thread principale cede il controllo.
Thread di comunicazione dellevento (event dispatch thread, EDT): esegue il codice
che gestisce gli eventi.
Questo thread viene creato appena appare la prima finestra. Gli eventi consistono
prevalentemente in eventi di aggiornamento che causano il ridisegno dei componenti
dellinterfaccia utente o eventi di input generati mediante tastiera o mouse. La maggior
parte dei metodi Swing devono essere eseguiti dallEDT perch alcuni metodi, detti non
thread safe, se eseguiti in altri thread possono danneggiare linterfaccia utente.
Altri metodi Swing, invece, sono thread safe e possono essere eseguiti in qualsiasi thread:
- i metodi repaint, revalidate, invalidate di JComponent;
- tutti i metodi del tipo addXXXListener e removeXXXListener;
- tutti i metodi esplicitamente documentati come thread safe.
Di conseguenza, nella maggior parte dei casi, quando si vuole aggiornare lo stato visivo
dei componenti dellinterfaccia utente consigliabile utilizzare EDT.
Thread di lavoro (worker thread o background thread): eseguono in background
elaborazioni considerate costose in termini di tempo e sono definiti dal programmatore.
Se unoperazione richiede molto tempo per essere completata, eseguirla nellEDT blocca
la GUI per tutta la durata delloperazione stessa e lutente non pu interagire con essa.
Per tale motivo questo tipo di elaborazioni vengono realizzate fuori dallEDT su un worker
thread.
Regole da seguire in unapplicazione Swing
1) Se unazione richiede molto tempo occorre attivare un nuovo thread per eseguirla, cos
da non bloccare lEDT, impedendo allinterfaccia di rispondere agli eventi dellutente.
Analogamente, occorre creare un nuovo thread se unoperazione pu bloccarsi su un
input o un output.
2) Se necessario attendere per un certo tempo meglio non bloccare lEDT ma
utilizzare un timer.
3ue Questultima regola chiamata anche regola del singolo thread.
La regola del singolo thread non vale per i metodi che utilizzano i thread in modo sicuro.
Inoltre, si tenga presente che uninterfaccia pu sempre essere modificata dallEDT fino a
quando nessuno dei componenti stato realizzato, cio fino a quando non viene chiamato
il metodo setVisible o pack.
La regola del singolo thread molto restrittiva, ma possibile aggirarla, grazie a due
metodi della classe EventQueue.
Regola del singolo thread e la classe EventQueue
La classe java.awt.EventQueue definisce due metodi statici, invokeLater e
invokeAndWait, che possono aggiungere operazioni alla coda di eventi per far s che
vengano eseguite nellEDT. Questi metodi sono presenti anche nella classe
javax.swing.SwingUtilities.
Bocchi Cinzia
10/01/2015
14
EventQueue.invokeAndWait(new Runnable() {
public void run() {
try {
//codice che aggiorna linterfaccia
} catch (Exception e) {
e.printStackTrace();
}
}
});
Possiamo migliorare il codice della classe MyFrame inserendo il codice del metodo main
dentro al metodo run, come mostrato nel seguente esempio.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
import java.awt.EventQueue;
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class MyFrame extends JFrame {
Bocchi Cinzia
public
public
public
public
static
static
static
static
final
final
final
final
int
int
int
int
WIDTH = 450;
HEIGHT = 300;
X = 100;
Y = 100;
public MyFrame() {
initialize();
}
10/01/2015
15
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Bocchi Cinzia
10/01/2015
16
Bocchi Cinzia
10/01/2015
17
mport java.awt.EventQueue;
import javax.swing.JFrame;
public class MyFrame {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MyFrame window = new MyFrame();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MyFrame() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
MyFrame versione Window Builder
Bocchi Cinzia
10/01/2015
18
A questo punto possiamo intervenire direttamente sul codice per modificare alcune
propriet del frame e per aggiungere componenti, oppure possiamo utilizzare la scheda
Design per effettuare tutte queste operazione in modo visuale.
Selezionando il frame con un clic del mouse, sono rese visibili le propriet dellelemento,
nellarea Properties.
Bocchi Cinzia
10/01/2015
19
Facendo clic sul pulsante racchiuso nellovale rosso della figura 6, si possono visualizzare
le propriet avanzate, mentre cliccando su quello racchiuso nellovale blu si ripristinano le
impostazioni di default.
Proviamo a inserire il titolo della finestra e ad aggiungere unicona (che deve essere
preventivamente caricata nel progetto).
Le modifiche si riflettono nel codice, in particolare nel metodo initialize, che diventa:
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(MyFrame.cla
ss.getResource("/frame4/duke_icon.jpg")));
frame.setTitle("MyFrame");
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Quest'opera distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0
Internazionale
Bocchi Cinzia
10/01/2015
20