[Per corso su Java vedere http://java.sun.com/docs/books/tutorial/]
Tutte le classi componenti hanno inoltre in comune
un insieme di eventi che possono catturare.
Queste caratteristiche comuni sono definite nella classe base
Component (in AWT) e JComponent (in Swing).
Nota: la classe JComponent deriva per ereditarieta' da
Component, per cui JComponent ha tutti i
metodi di Component ed altri in piu'.
Esempio:
Ogni componente ha anche due allineamenti (orizzontale, verticale)
di cui il layout manager puo' tenere conto.
Queste dimensioni e
allineamenti sono stabiliti dal sistema in modo generalmente sensato
(es. per un bottone la dimensione preferita e' quella grande a
sufficienza per mostrare tutta l'etichetta e non piu' grande del
necessario).
Java AWT fornisce metodi solo per leggere queste dimensioni e
allineamenti (nome che inizia per "get"),
mentre non posso assegnarli esplicitamente.
Nota: nelle varie sotto-classi di componenti alcuni di questi
eventi sono gestiti internamente. Esempio: un campo di input testuale
reagisce a guadagno / perdita del focus e a battitura di
caratteri da tastiera in modo autonomo.
Tutti i metodi dei listener hanno parametri come segue:
MouseListener reagisce a tutti gli eventi tranne quelli
di movimento, con i metodi:
MouseMotionListener reagisce agli eventi di movimento
del mouse, con i metodi:
Quando distruggo un frame, distruggo anche tutti i suoi dialoghi.
Quando iconifico / deiconifico il frame, spariscono / riappaiono
i suoi dialoghi.
Questo comportamento e' gestito automaticamente dal sistema.
Crea dialogo dipendente da myframe (al posto di un frame
potrei avere un altro dialogo).
Il titolo apparira' sulla
barra aggiunda da WM (se la aggiunge) alla finestra del dialogo.
La costante true/false indica se il dialogo sara' modale o no
(per default non e' modale).
Classe JOptionPane ha metodi per mostrare dialoghi modali
associati ad un frame:
showMessageDialog (con un bottone), showOptionDialog
(con numero di bottoni a piacere), ed altri.
Esempio 1:
Esempio 2:
Esistono anche dialoghi predefiniti che consentono immissione di una
stringa.
I metodi ShowXXXDialog ritornano una costante indicante il
bottone premuto:
JDialog.OK_OPTION,
JDialog.YES_OPTION, JDialog.NO_OPTION,
JDialog.CANCEL_OPTION (se 3 bottoni).
Oppure JDialog.CLOSE_OPTION se dialogo chiuso agendo sul
bordo della finestra.
L'optione selezionata in un JOptionPane si legge con:
Il WindowListener corrispondente prevede i seguenti metodi
di reazione ad eventi:
Per cambiare il layout manager (prima di aggiungere componenti):
Suggerimenti sono relativi a: dimensioni minime, massime, preferite,
e allineamento.
Da chiamare dopo aver aggiunto tutte le componenti e
sottocomponenti alla finestra e prima di mapparla.
Creazione in AWT:
Creazione in Swing:
Aggiungere la componente con "add" non sembra funzionare.
Importante impostare le dimensioni del pannello
(con setPreferredSize), altrimenti
per default il pannello si dimensiona grande quanto la componente
contenuta al suo interno.
Contiene due componenti dalle parti opposte del divisorio.
L'utente puo' trascrinare col mouse il divisorio per stabilire
quanto spazio va dato a ciascuna delle due parti.
Solo Swing:
Se non ho specificato le due componenti alla creazione,
Posso aggiungerle dopo con add nella sua prima
forma (la prima componente aggiunta e' quella in alto / a sinistra),
oppure con
setTopComponent(Component) e analogo con Bottom, Left,
Right.
Per default il pannello determina la posizione del divisorio in base
alle dimensioni preferite dei due componenti che contiene.
Per spostare il divisorio:
Ci sono altri metodi per stabilire allineamento orizzontale / verticale,
spaziatura.
Esempi in Swing:
La prima chiamata e' legale anche con Button o
Checkbox (AWT).
In ciascuna finestra top-level posso definire al piu' un solo
bottone "di default" che e' sensibile anche alla pressione del tasto
"return" (il sistema distingue graficamente tale bottone).
In Swing:
boolean isSelected() ritorna se componente selezionato
La pressione di un bottone del gruppo provoca automaticamente il rilascio di
tutti gli altri bottoni del gruppo. Gruppi di radio-bottoni servono a
implementare scelte mutuamente esclusive.
Creo le varie voci separatamente e poi le aggiungo ad un
Menu / JMenu.
Un Menu / JMenu puo' essere usato come voce di un altro menu',
realizzando in tal modo un menu' a cascata.
Esempio:
In piu' in Swing posso mettere testo e/o icone nelle voci di menu':
In piu' in Swing ho classe JRadioBoxMenuItem per
realizzare voci a due stati mutuamente esclusive.
Le voci che sono sottomenu' le gestisce automaticamente il sistema
(la loro reazione e' mostrare la tendina del sottomenu').
Generalita' sui componenti Java
Tutte le classi componenti hanno in comune
un insieme di metodi per leggere / assegnare certe proprieta'
generali.
Metodi comuni a tutti i componenti
Visibilita'
Mappatura di un componente su schermo:
Componenti NON sono mappati automaticamente.
Occorre mappare i componenti top-level (frame, dialoghi), il che provoca
automaticamente mappatura di tutti i sotto-componenti.
Abilitazione
Per abilita' si intende capacita' di un componente
ad interagire con l'utente.
Colori e font
comp.setFont("Helvetica",Font.PLAIN,14) assegna
font Helvetica normale a dimensione 14 punti.
comp.setBackground(new Color(0.6,0.3,1.0))
assegna colore di sfondo mediante le sue componenti Red Green Blue.
Bordi (solo Swing)
I bordi servono non solo come ornamento ma anche per raggruppare
assieme dispositivi logicamente correlati, eventualmente aggiungendo
un titolo.
Ci vari tipi di bordi, in un bordo si possono inserire titoli e/o grafica.
Esempi:
comp.setBorder(BorderFactory.createLineBorder(Color.black));
crea bordo a linea semplice, nero, senza titolo
b1 = BorderFactory.createLineBorder(Color.black);
b2 = BorderFactory.createTitledBorder(b1,"titolo",
TitleBorder.CENTER,TitleBorder.BELOW_BOTTOM);
comp.setBorder(b2);
crea bordo come prima piu' titolo posizionato al centro sotto
il riquadro incorniciato dal bordo.
Messaggi in sovra-impressione (solo Swing)
Riga di spiegazione a comparsa e scomparsa. Associabile a qualsiasi
componente.
Appare quando utente si ferma col mouse sopra la componente.
comp.setToolTipText("Questo e' il messaggio");
Dimensioni e allineamenti
Ogni componente ha tre dimensioni (minima, massima, preferita)
di cui il layout manager del contenitore in cui la componente si trova
puo' tenere conto.
Java Swing fornisce anche metodi per assegnarle
(nome che inizia per "set").
Altri metodi relativi alle dimensioni:
Il parametro e' un numero tra 0 e 1 che specifica come
questa componente e' allineata a quella vicina:
0 = allineamento all'origine,
1 = allineamento all'estremita' opposta all'origine,
0.5 = allineamento centrato, ecc.
Eventi comuni a tutti i componenti
Classi di eventi che qualsiasi componente puo' catturare:
Per ciascuna di queste classi, alla componente posso associare un
listener.
public void nomefunzione(XXXEvent e)
Posso chiamare su e i metodi della classe di evento
XXXEvent per reperire informazioni che servono per
reagire all'evento.
Esempio:
oppure convertirlo nella particolare classe della
componente a cui e' associato il listener dell'evento.
Eventi di componente
ComponentListener prevede i seguenti metodi di reazione
ad eventi:
Focus della tastiera
FocusListener prevede i seguenti metodi:
Input da tastiera
KeyListener prevede i seguenti metodi:
La pressione di un carattere stampabile fa scattare tutti e tre
i metodi, quella di un tasto non stampabile fa scattare i primi due.
Al carattere stampabile si accede con e.getKeyChar()
(dove e e' l'evento di classe KeyEvent) e al codice
del carattere con e.getKeyCode().
Eventi da mouse
La classe di eventi MouseEvent ha due listener.
Si e' ritenuto opportuno separare gli eventi di movimento del mouse,
che comportano molto lavoro per gestirli
(ogni movimento di un pixel genera un evento)
e definire un listener a parte per questi.
Se e e' l'evento di classe MouseEvent,
la posizione del mouse all'interno del sistema
di coordinate della componente si ottiene con e.getX(),
e.getY()(in pixel).
Il click del mouse scatena tre reazioni: pressione, rilascio, click.
Il numero di pressioni e rilasci contenuti nel
click si legge con e.getClickCount() (click semplice, doppio...).
Finestre (contenitori) top-level
Classe Frame / JFrame
Finestra top-level con tutte le decorazioni del WM (window manager):
bordo, barra del titolo, controlli (per chiusura, iconificazione ecc.).
Serve come finestra primaria di un'applicazione.
Creazione
Frame myframe = new Frame();
Frame myframe = new Frame("titolo");
e uguale con JFrame.
Il titolo apparira' sulla barra del titolo aggiunta dal WM.
Barra di menu'
Un frame puo' avere una barra di menu' (classe MenuBar
o JMenuBar). Per aggiungere la barra di menu' ad un frame:
mymenubar = new JMenuBar();
myframe.setMenubar(mymenubar);
Alla barra di menu' poi aggiungero' menu' (ved.
piu' avanti).
Contenuto di un frame
Oltre alla barra di menu' (se presente), un frame e' vuoto.
Per riempirlo devo aggiungere componenti
Istruzioni su aggiunta di componenti in un contenitore sono
piu' avanti.
myframe.add(...)
Container mycontent = myframe.getContentPane();
mycontent.add(...)
Classe Dialog / JDialog
Finestra top-level dipendente funzionalmente da un'altra (tipicamente
da un frame), intesa come finestra temporanea.
Puo' avere tutte o un sottoinsieme delle decorazioni, dipende dal WM.
Usata come finestra secondaria di un'applicazione
per mostrare informazioni e richiere input (finestra di dialogo).
Creazione
mydialog = new Dialog(myframe);
mydialog = new Dialog(myframe, "titolo");
mydialog = new Dialog(myframe, true/false);
mydialog = new Dialog(myframe, "titolo", true/false);
e uguale con JDialog.
Proprieta' dei dialoghi
Contenuto
Il dialogo creato e' vuoto. Per definirne il contenuto devo aggiungere
componenti, nello stesso modo in cui si fa per i frame
(cioe' diverso in AWT e Swing, ved.
sopra).
Dialoghi pronti all'uso
In Swing esistono option panels, tipi di pannelli predefiniti
da mostrare dentro un dialogo, che contengono:
Creo un JOptionPane e da questo un dialogo che lo contiene.
Esempio:
JOptionPane myoption = new JOptionPane ("messaggio",
JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION);
JDialog mydialog = myoption.createDialog(myframe,"titolo");
mydialog.pack();
crea dialogo che dipende funzionalmente da myframe
avente come pannello di contenuto myoption, che si
presenta cosi':
I due bottoni presenti nel pannello hanno automaticamente
l'effetto di chiudere la finestra di dialogo, quando premuti.
JOptionPane.showMessageDialog(myframe, "messaggio", "titolo",
JOptionPane.PLAIN_MESSAGE);
Il messaggio e' mostrato nella finestra, il titolo apparira'
sulla barra del titolo aggiunta dal WM (se sara' aggiunta).
PLAIN_MESSAGE significa che non e' presente
l'icona, alternative: WARNING_MESSAGE,
ERROR_MESSAGE, INFORMATION_MESSAGE...
Object[] options = {"questa", "quella", "l'altra"};
int n = JOptionPane.showOptionDialog(myframe, "Quale delle tre?", "titolo",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
new ImageIcon("myicon.gif"), options, options[2]);
Mostra dialogo con tre bottoni (YES_NO_CANCEL_OPTION),
le cui etichette sono le tre stringhe contenute in options,
e l'opzione di default e' la terza, l'icona e' presa dal file myicon.gif:
Quale bottone e' stato azionato nel dialogo
Premere uno dei bottoni presenti sul dialogo ne provoca la chiusura.
int n = (Integer)myoption.getValue().intValue();
Eventi di finestra
I contenitori top-level (frame e dialoghi) possono catturare eventi di
classe WindowEvent.
Metodi
Metodi utili comuni a tutte le finestre top-level:
Prima di mappare una finestra, occorre sempre stabilirne la dimensione
con setSize o pack.
Uso dei contenitori
Tutti i contenitori hanno un metodo che stabilisce il layout manager
e un metodo che consente di aggiungere componenti nel contenitore.
Layout manager
Per default, il layout manager e' sempre FlowLayout.
mycontainer.setLayout(mylayout);
Il metodo per creare il layout manager dipende dalla classe.
Parametri comuni sono:
Classe FlowLayout
mylayout = new FlowLayout();
mylayout = new FlowLayout(allineamento);
mylayout = new FlowLayout(spazX,spazY);
mylayout = new FlowLayout(allineamento,spazX,spazY);
dove l'allineamento puo' essere FlowLayout.LEFT,
FlowLayout.RIGHT oppure FlowLayout.CENTER
(componenti allineate a sinistra, a destra o centrate).
Classe GridLayout
mylayout = new GridLayout(numrighe,numcolonne);
mylayout = new GridLayout(numrighe,numcolonne,spazX,spazY);
Classe BorderLayout
mylayout = new BorderLayout();
mylayout = new BorderLayout(spazX,spazY);
Non vediamo GridBagLayout, la cui gestione e' piuttosto complicata.
Classe BoxLayout
Solo in Swing, organizza componenti in riga o colonna.
mylayout = new BoxLayout(contenitore,direzione);
Dove contenitore e' quello a cui verra' associato il layout manager,
direzione puo' essere BoxLayout.X_AXIS oppure
BoxLayout.Y_AXIS.
BoxLayout ha metodi particolari per controllo accurato di
allineamento, spaziatura, dimensioni delle componenti al suo interno.
Aggiunta di componenti
Il metodo add della classe contenitore
consente di aggiungere oggetti:
mycontainer.add(componente);
mycontainer.add(componente,posizione);
Se il contenitore ha layout manager FlowLayout o GridLayout
(o BoxLayout), allora si usa la prima forma di add:
Se il contenitore ha layout manager BorderLayout,
allora si usa la seconda forma di add, dove la posizione
e' una fra BorderLayout.NORTH, BorderLayout.SOUTH,
BorderLayout.EAST, BorderLayout.WEST, BorderLayout.CENTER
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 5 | 6 | 7 | 8 |
+---+---+---+---+
+--------------------------+
| NORTH |
+------+------------+------+
| EAST | CENTER | WEST |
+------+------------+------+
| SOUTH |
+--------------------------+
Il contenitore e' diviso in 5 zone, ciascun componente va aggiunto
ad una zona specifica, non mettere piu' di un componente per zona!
E' permesso lasciare vuote alcune zone.
Suggerimenti al layout manager
Componenti possono dare suggerimenti al layout manager, ma
l'ultima decisione spetta a questo.
Impacchettamento
I contenitori top-level hanno metodo pack,
che
assegna le dimensioni della finestra e di tutto il
suo contenuto tenendo conto delle dimensioni preferite
della finestra e del layout delle sue sottocomponenti.
Rimozione di componenti
Posso aggiungere e anche togliere componenti da un contenitore
a run-time.
Simmetrico al metodo add esiste metodo remove.
Alcune classi di contenitori intermedi
Pannelli a scomparto unico
Classe Panel / JPanel
Senza barre di scorrimento. Creazione:
mypanel = new Panel();
mypanel = new Panel(mylayout);
Analogo con JPanel.
Se non specificato, il layout manager e' FlowLayout.
Classe ScrollPane / JScrollPane
Con barre di scorrimento.
Consente di visualizzare (una parte alla volta) un contenuto piu' grande
dell'area occupata sullo schermo dal pannello.
mypanel = new ScrollPane();
mypanel = new ScrollPane(scrolling);
Dove scrolling determina il criterio usato per decidere
se ci sono le barre, e puo' essere uno tra
ScrollPane.SCROLLBARS_ALWAYS (barre sempre),
ScrollPane.SCROLLBARS_AS_NEEDED (solo se il
contenuto e' piu' grande del contenitore),
ScrollPane.SCROLLBARS_NEVER (mai).
Se non specificato, per default e' "as needed".
La componente dentro lo scrolled pane si aggiunge con "add".
mypanel = new JScrollPane();
mypanel = new JScrollPane(comp);
mypanel = new JScrollPane(scrollY,scrollX);
mypanel = new JScrollPane(comp,scrollY,scrollX);
Dove comp e' la componente da collocare all'interno del pannello.
I parametri scrollY e scrollX controllano separatamente
la presenza / assenza delle barre e possono valere
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
(e idem per HORIZONTAL).
Pannelli bipartiti
Pannello bipartito con linea di divisione
orizzontale o verticale.
mypanel = new JSplitPane();
mypanel = new JSplitPane(direzione);
mypanel = new JSplitPane(true/false);
mypanel = new JSplitPane(direzione,comp1,comp2);
mypanel = new JSplitPane(direzione,true/false,comp1,comp2);
La direzione e' una fra JSplitPane.HORIZONTAL_SPLIT (defalult)
e JSplitPane.VERTICAL_SPLIT.
La costante booleana indica se il contenuto dei due scomparti viene
ridisegnato in tempo reale mentre l'utente sposta il divisorio
(per default no).
I parametri comp1, comp2 sono le due componenti da mettere nei due
scomparti (la prima e' quella in alto / a sinistra).
Contenuto
Uno split pane puo' contenere solo due componenti e non ha bisogno
di specificare layout manager.
Posizione del divisorio
Posso cambiare la direzione del divisorio con
setOrientation(direzione).
mypanel.setDividerLocation(percentuale);
mypanel.setDividerLocation(pixel);
Le posizioni ammissibili per il divisorio risentono delle dimensioni
minime dei due componenti che contiene.
Alcune classi di dispositivi
Etichette
Classe Label, JLabel e' etichetta testuale in AWT,
testuale e/o grafica in Swing.
Creazione in AWT
Label label = new Label("stringa di testo");
Creazione in Swing
ImageIcon icon = new ImageIcon("immagine.gif");
label1 = new JLabel("solo testo");
label2 = new JLabel("testo e immagine",icon);
label3 = new JLabel(icon);
Puo' esserci un ultimo argomento: l'allineamento, che puo' essere
JLabel.LEFT, JLabel.RIGHT, JLabel.CENTER,
JLabel.LEADING, JLabel.TRAILING.
Bottoni
Creazione
In AWT il creatore prende come argomento una stringa
(etichetta da visualizzare).
In Swing prende una stringa, un'icona, oppure una stringa e un'icona.
mybutton = new JButton("titolo");
mybutton = new JButton("titolo",icona);
mybutton = new JButton(icona);
Stessa cosa si puo' fare con JCheckBox, con in piu'
un ultimo argomento booleano opzionale che stabilisce se il
bottone e' inizialmente selezionato o no (di default non e' selezionato).
Reazione a eventi
Il corrispondente ActionListener ha un solo metodo
actionPerformed che scatta quando il bottone e' azionato.
finestratop.getRootPane().setDefaultButton(bottone);
ItemListener prevede un solo metodo
ItemStateChanged, che scatta quando il bottone cambia stato
(da selezionato a deselezionato o viceversa).
Il programma legge il nuovo stato con
int getStateChange() che ritorna
uno fra ItemEvent.SELECTED e ItemEvent.DESELECTED.
Alcune funzioni utili su bottoni a due stati
Per selezionare / controllare se e' selezionato:
setSelected(boolean) forza selezione
boolean isSelected() ritorna true se componente selezionato
setSelected(boolean) forza selezione
Gruppi di bottoni radio
Gruppo di bottoni radio e' un gruppo di bottoni a due stati dove
in ogni istante un solo bottone puo' essere selezionato.
In AWT
Esempio:
CheckboxGroup cbg = new CheckboxGroup();
b1 = new Checkbox("uno", cbg, true);
b2 = new Checkbox("due", cbg, false);
b3 = new Checkbox("tre", cbg, false);
L'ultimo argomento booleano stabilisce se il bottone e' inizialmente
selezionato (di default non e' selezionato).
In Swing
Esempio:
rb1 = new JRadioButton("uno",true);
rb2 = new JRadioButton("due");
rb3 = new JRadioButton("tre");
ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
Radio button cattura eventi ActionEvent e ItemEvent.
Quando utente preme un bottone radio in un gruppo,
si generano tre eventi:
Menu' e voci di menu'
Menu' permette
scelta di un'opzione da una lista di voci che e' presentata come
una tendina a scomparsa.
Creazione di menu'
Un menu' puo' essere:
Esempio di menu' inseriti in barra:
mybar = new MenuBar();
myframe.setMenuBar(mybar);
menu1 = new Menu("Primo menu'");
mybar.add(menu1);
menu2 = new Menu("Altro menu'");
mybar.add(menu2);
Analogamente si crea menu' pop-up:
mypop = new PopupMenu("Menu' pop-up");
Codice analogo nel caso Swing.
Definizione delle voci di menu'
Ogni voce del menu' (menu item) ha caratteristiche analoghe a un bottone.
Le classi di voci di menu' rispecchiano le classi di bottoni:
MenuItem, CheckBoxMenuItem, in AWT,
JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem in Swing.
menu1 = new Menu("Primo menu'");
menu1.add (new MenuItem("voce semplice"));
menu1.add (new CheckboxMenuItem("voce a due stati"));
menu2 = new Menu("sotto menu'");
menu1.add (menu2);
menu2.add("una voce");
menu2.add("altra voce");
Crea un menu' (menu1) con tre voci: una
semplice, una a check box e una costituita da un sottomenu' (menu2).
item = JMenuItem(stringa);
item = JMenuItem(icona);
item = JMenuItem(stringa,icona);
Analogo per JCheckBoxMenuItem con in piu' ultimo argomento
booleano (opzionale) che specifica se voce e' inizialmente selezionata
o no.
Eventi nei menu'
Quelle che reagiscono a eventi sono le singole voci dei
menu'.
Menu' pop-up
Per assegnare un menu' pop-up ad un componente, si associa a quel componente
un MouseListener che faccia apparire il menu' pop-up
quando l'utente aziona il mouse.
Esempio:
public class PopFrame extends Frame
{
PopupMenu popup;
public PopFrame()
{
Label label = new Label("Try bringing up a popup menu!");
add(label);
popup = new PopupMenu("A Popup Menu");
add(popup);
MenuItem mi1 = new MenuItem("aaa");
popup.add(mi1);
MenuItem mi2 = new MenuItem("bbb");
popup.add(mi2);
MouseListener listener = new PopupListener();
addMouseListener(listener);
label.addMouseListener(listener);
}
class PopupListener extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e)
{
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e)
{
if (e.isPopupTrigger())
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
Keyboard alternatives
Scorciatoie da tastiera.
Esistono appositi metodi per associare mnemonici e acceleratori
alle voci di menu'.