Swing e la programmazione a eventi
Lo stile basato su eventi
I componenti interagiscono attraverso l’invio di messaggi broadcast
o multicast
“Attenzione! C’è un incendio”
“Si avvisano i signori passeggeri che …”
Ogni componente notifica un cambiamento nel proprio stato o in
quello dell’ambiente inviando un messaggio
Tutti i componenti interessati all’evento descritto da tale messaggio
ne ricevono copia
In tal caso agisce da “generatore dell’evento”
In tal caso agiscono da “ascoltatori dell’evento”
In generale, il generatore dell’evento non conosce né il numero né
l’identità degli ascoltatori
2
Caratteristiche generali
Con il paradigma a eventi
L’applicazione è puramente “reattiva”
Non è possibile identificare staticamente un flusso di controllo unitario
Il programma principale si limita a inizializzare l’applicazione, istanziando
gli osservatori e associandovi gli opportuni handler
Occorrenza
dell’evento A
Occorrenza
dell’evento B
Realtà
Applicazione
Osservatori
Notifica
dell’evento A
Ascoltatore
evento A
Notifica dell’evento B
Ascoltatore
evento A
Ascoltatore
evento B
listeners
3
Vantaggi
Utili per sistemi altamente dinamici ed evolutivi, in cui nuovi moduli
si possono aggiungere o possono essere eliminati
Per comunicare tra di loro, i moduli non devono conoscere le
rispettive identità
come invece accade in Java
nomeModulo.nomeServizio (parametri)
Si parla più in generale di paradigma di progettazione "publish and
subscribe"
moduli che generano eventi ("publish")
moduli che sottoscrivono l'interesse ad essere notificati dell'occorrenza
di certi eventi ("subscribe")
4
In pratica
subscribe y
x
Gestore degli eventi
y
subscribe z
subscribe x
5
Modello a eventi in Java
Un’applicazione può essere costruita come componenti che
interagiscono attraverso eventi
Utilizzando le convenzioni dei JavaBean
Qui noi vediamo il package javax.swing
libreria che fornisce le classi che consentono la progettazione delle
interfacce utente secondo lo stile ad eventi
6
Swing
GUI
GUI: Graphical User Interface
L'interfaccia utente costituisce il mezzo con il quale l'utente
interagisce con l'applicazione
costituisce il "look&feel"
Fondamentale per l'usabilità del software
Come si progetta?
8
Progettazione
Separare GUI e parte funzionale
La GUI si preoccupa di interagire con l'utente
visualizzare
accettare input
La parte funzionale contiene la logica applicativa
Vantaggi
GUI modificabile senza toccare la parte funzionale e viceversa
Diverse strategie "look&feel" per la stessa applicazione
Spesso le modifiche si incentrano sulla GUI al fine di migliorare l'usabilità
9
Model-View-Controller
Swing si basa su un “paradigma” di progettazione che si incontra
anche in altri campi:
Un componente ha un suo “modello logico”
Un componente ha un suo “aspetto visuale”
Un componente ha “comportamenti” che consentono la sua interazione
con il resto dell’applicazione
Esempio -> JButton
Model: Premuto/Rilasciato (variabile booleana)
View: dipende dal look&feel
Controller: ActionPerformed della classe ActionListner collegata al
JButton (ci torneremo)
10
AWT e Swing
Abstract Windowing Toolkit (AWT)
Sono un residuo di precedenti versioni di JAVA fornisce ancora alcune importanti
componenti al funzionamento e creazione di elementi di interfaccia
Swing
Consentono di realizzare applicazioni con un “look and feel” più aggiornato e
elegante
Si basano su un modello di interazione introdotto da JAVA2
Hanno superato alcuni dei difetti di AWT
Chiedono servizi al sistema operativo, ma (normalmente) ad un livello più basso e
riescono così ad avere un maggiore controllo del “look&feel”
Sono una “estensione” del core di JAVA e possono risultare più complesse da
programmare
Consentono un maggior controllo del look&feel di un’applicazione e garantiscono il
medesimo look&feel su tutte le piattaforme
11
AWT e Swing
Il nome di tutti i componenti Swing inizia con J
I componenti Swing sono lightweight
La convenzione è JXxxx
Vengono creati disegnandoli nella finestra sottostante
È bene non includere componenti Swing ed AWT in una stessa
interfaccia:
I componenti AWT (heavyweight) vengono sempre mostrati “sopra” i
componenti Swing (ad esempio con i Menu)
Problema dovuto alla mancanza di compatibilità fra i due framework
12
Un’interfaccia Swing
Tre elementi fondamentali
Contenitori
Elementi grafici
Eventi
13
Frame
Un frame
Definisce l’intelaiatura dell’interfaccia
Fornisce un rettangolo, “decorato” alla maniera delle finestre cui siamo
abituati
E’ un oggetto COMPLESSO!
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
14
JFrame
Come in tutta la programmazione ad
oggetti occorre conoscere la “gerarchia”
entro la quale si colloca JFrame
Per conoscere la “derivazione” di ogni
oggetto delle librerie GUI di Swing si deve
fare ricorso alla documentazione in linea
di Java
java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
http://java.sun.com/j2se/1.5/docs/api/
java.awt.Frame
javax.swing.JFrame
15
JFrame
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
16
Scorrendo la gerarchia
Component
“A component is an object having a graphical representation that can be
displayed on the screen and that can interact with the user. Examples of
components are the buttons, checkboxes, and scrollbars of a typical
graphical user interface”
Component è quindi una classe molto generale e definisce un sacco di
metodi
Container
Un Component con la proprietà di essere abilitato a contenere altri
Component
Prevede metodi di tipo “add” per aggiungere componenti
Prevede anche metodi per rappresentare il contenitore e i suoi contenuti
e per aggiornarne l’immagine
17
Scorrendo la gerarchia
Window
È un particolare contenitore che può apparire sullo schermo come entità propria,
ma non ha bordi, barre e controlli
Possiede metodi per mostrare la finestra, nascondere la finestra, posizionare la
finestra e aggiustare l’ordine di comparizione relativamente ad altre finestre
Frame
Si tratta di Window con bordi e barra del titolo, oltre alle caratteristiche solite di
un’interfaccia (minimizzazione, iconizzazione, chiusura, resizing)
JFrame
È un Frame AWT a cui SWING aggiunge una serie di metodi per ridefinire i
dettagli grafici. Ad esempio
l metodo setSize(int l, int h) permette di determinare le dimensioni del Frame
Il metodo setLocation(int x, int y) consente di definire le coordinate del pixel in alto
a sinistra del frame nel riferimento dello schermo
18
Cosa possiamo fare con un JFrame?
Non possiamo disegnare, scrivere o aggiungere elementi
direttamente al Frame
Gli elementi diversi dal Menu debbono essere “aggiunti” ad un
Container opportuno
Ad esempio
Per scrivere del testo dentro un Frame, il testo dovrà essere scritto
(aggiunto) al pannello contentPane del JFrame
Per convenienza il metodo add() di JFrame si occupa di tutto il lavoro
frame.getContentPane().add(label) = frame.add(label)
19
HelloWorldSwing
import javax.swing.*;
public class HelloWorldSwing {
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing");
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
createAndShowGUI();
}
}
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
20
HelloWorldSwing (seconda versione)
import javax.swing.*;
public class HelloWorldSwing {
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
createAndShowGUI();
}
}
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
21
Look&feel
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
22
Look&feel nativo
public class WindowUtilities {
public static void setNativeLookAndFeel() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
System.out.println(“Problema Look and feel nativo” + e);
}
}
23
Aggiungiamo componenti
Dobbiamo sapere:
Da dove prendere i componenti?
Come costruirli e personalizzarli?
Costruttori e modificatori
Come usarli?
Una lista/descrizione delle librerie disponibili
Quali eventi sono in grado di raccogliere e quali i listener necessari
Come disporli sui frame che costituiscono la nostra applicazione?
Layout manager
24
Container
Top-level container
JApplet
JDialog
General-purpose containerJScrollPane
JPanel
JFrame
JSplitPane
JTabbedPane
25
Container
Special-purpose container
JInternalFrame
JLayeredPane
JToolBar
Permette di semplificare
l’attivazione di determinate
funzioni per mezzo di semplici
pulsanti
Permette di inserire frame dentro
altri frame
Permette di inserire
componenti a vari
livelli di profondità
26
Controlli di base
JButtons
Include buttons,
radioButtons, checkbox,
MenuItem, ToggleButton
JComboBox
JSlider
JList
JMenu
JTextField
Include
JPasswordField,
JTextArea
27
Visualizzatori di informazioni non editabili
JLabel
JProgressBar
Jcomponent.setToolTipText(String)
Può includere
immagini e/o testo
28
Visualizzatori di informazioni formattate editabili
JColorChooser
JFileChooser
JTable
JTextComponent
JTree
JTextField,
JPasswordField,
JTextArea, JEditorPane,
JTextPane
29
Altri componenti grafici
Label
Button
CheckBoxButton
ScrollBar
PullDownMenu
PopupMenu
…
30
Layout
Java gestisce la disposizione dei componenti dentro i Container
mediante oggetti che si chiamano LayoutManager
È un’interfaccia che descrive come un componente deve
comunicare con il suo LayoutManager
Esiste un’ampia collezione di LayoutManager, ma se si vuole si può
creare il proprio
Incapsulano gli algoritmi per il posizionamento delle componenti di una
GUI
Il LayoutManager mantiene l’algoritmo separato in una classe a parte
Noi vediamo solo i LayoutManager più comuni: FlowLayout,
BorderLayout, GridLayout, CardLayout e GridBagLayout
L’associazione avviene tramite il metodo setLayout() di cui è
provvista la classe Container (e quindi tutte le sue sottoclassi)
p.setLayout(new BorderLayout());
31
FlowLayout
E’ il più semplice. La sua strategia
è:
Rispettare la dimensione di tutti i
componenti
private static void createAndShowGUI() {
JFrame frame = new JFrame("Flow");
Disporre i componenti in
orizzontale finché non viene
riempita tutta una riga, altrimenti
iniziare su una nuova riga
frame.setLayout(new FlowLayout());
Se non c’è spazio i componenti
non vengono visualizzati
frame.add(new JButton("Button3"));
frame.add(new JButton("Button1"));
frame.add(new JButton("Button2"));
frame.add(new JButton("Button4"));
frame.add(new JButton("Button5"));
frame.pack();
frame.setVisible(true);
}
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
32
BorderLayout
Definisce 5 aree logiche: NORTH, SOUTH, CENTER, EAST e WEST
Richiede la dimensione preferita del componente (altezza e larghezza)
Se il componente è NORTH o SOUTH setta l’altezza al valore preferito e la
larghezza in modo da occupare tutto lo spazio orizzontale
Se il componente è EAST o WEST setta la larghezza al valore preferito e
l’altezza in modo da occupare tutto lo spazio verticale restante
Se il componente è CENTER setta l’altezza e la larghezza in modo da
occupare tutto lo spazio centrale restante
Quindi
Le posizioni NORTH e SOUTH servono quando vogliare fissare l’altezza di un
componente al valore preferito
Le posizioni EAST e WEST servono quando vogliamo fissare la larghezza di un
componente al valore preferito
La parte CENTER è quella che si espande
33
Esempio
private static void createAndShowGUI() {
JFrame frame = new JFrame("Border");
frame.setLayout(new BorderLayout());
frame.add(new JButton("North"), BorderLayout.NORTH);
frame.add(new JButton("South"), BorderLayout.SOUTH);
frame.add(new JButton("Center"), BorderLayout.CENTER);
frame.add(new JButton("West"), BorderLayout.WEST);
frame.pack();
frame.setVisible(true);
}
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
34
GridLayout
Dispone i componenti su una griglia
private static void createAndShowGUI() {
JFrame frame = new JFrame("Grid");
frame.setLayout(new GridLayout(3,4));
for (int x=1; x<13; x++)
frame.add(new JButton(""+x));
frame.pack();
frame.setVisible(true);
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
}
35
Stratificazione
private static void createAndShowGUI() {
JFrame f = new JFrame(”Example");
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
f.setLayout(new BorderLayout());
p2.setLayout(new FlowLayout());
p4.setLayout(new BorderLayout());
p4.add(new JButton("Button1"), BorderLayout.EAST);
p4.add(new JButton("Button2"), BorderLayout.WEST);
p2.add(p3);
p2.add(p4);
f.add(p1, BorderLayout.NORTH);
f.add(p2, BorderLayout.SOUTH);
f.pack();
f.setVisible(true);
}
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
36
Eventi
L’interazione tra gli elementi dell’interfaccia e la logica applicativa è
gestita tramite eventi
Gli EventListener sono interfacce definite per catturare e processare
tipi di eventi particolari
Un listener deve
Essere associato al componente
Essere informato quando il componente genera un evento del tipo
richiesto
Rispondere facendo qualcosa di appropriato
37
EventHandler
Devono avere tre pezzi di codice
Dichiarazione
Estendono o implementano listener esistenti
public class MyClass implements ActionListener {
Associazione tra handler (ovvero listener) e istanza
someComponent.addActionListener(instanceOfMyClass);
Definizione del codice che implementa i metodi dell’interfaccia listener
public void actionPerformed(ActionEvent e) { ...
38
Un primo esempio
public class Demo extends JFrame implements ActionListener {
JButton b = new JButton("Click me!");
public Demo() {
b.addActionListener(this);
getContentPane().add(b);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
}
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
b.setBackground(Color.RED);
39
Eventi e Listener
Categoria
Evento
handler
Mouse
MouseEvent
MouseListener,
MouseMotionListener
Keyboard
KeyEvent
KeyListener
Selezione elem
ItemEvent
ItemListener
input di testo
TextEvent
TextListener
scrollbar
AdjustmentEvent
AdjustmentListener
bottoni, menu,...
ActionEvent
ActionListener
cambiamenti nella finestra
WindowEvent
WindowListener
focus
FocusEvent
FocusListener
40
Esempio completo (parte I)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CheckDemo {
static JFrame jframe = new JFrame("Example");
public static void setupjframe() {
jframe.setSize(400,100);
jframe.setVisible(true);
jframe.getContentPane().setLayout( new FlowLayout() );
WindowListener l = new MyWindowAdapter();
jframe.addWindowListener(l);
}
41
Esempio completo (parte II)
public static void main(String[] args) {
setupjframe();
JCheckBox jck1 = new JCheckBox("Pepperoni");
JCheckBox jck2 = new JCheckBox("Mushroom");
JCheckBox jck3 = new JCheckBox("Black olives");
JCheckBox jck4 = new JCheckBox("Tomato");
jck1.addActionListener(new MyActionListener());
jck2.addItemListener(new MyItemListener());
Container c = jframe.getContentPane();
c.add(jck1);
c.add(jck2);
c.add(jck3);
c.add(jck4);
jframe.pack();
}
}
42
Esempio completo (parte III)
ActionEvent
public class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e)
{ System.out.println("event = " + e); }
}
ItemEvent
public class MyItemListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange()==e.SELECTED)
System.out.print("selected ");
else System.out.print("de-selected ");
System.out.print("Mushroom\n");
}
}
43
Esempio completo (parte IV)
WindowEvent
public class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent e) {System.exit(0);}
}
44
Altro esempio
public class SwingApplication implements ActionListener {
private static String labelPrefix = "Number of button clicks: ";
private int numClicks = 0;
final JLabel label = new JLabel(labelPrefix + "0 ");
public Component createComponents() {
JButton button = new JButton("I'm a Swing button!");
button.setMnemonic(KeyEvent.VK_I);
button.addActionListener(this);
label.setLabelFor(button);
JPanel pane = new JPanel(new GridLayout(0, 1));
pane.add(button);
pane.add(label);
pane.setBorder(BorderFactory.createEmptyBorder(
30, //top
30, //left
10, //bottom
30) //right
);
return pane;
QuickTimeᆰ and a
TIFF (LZW) decompressor
are needed to see this picture.
45
Altro esempio
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText(labelPrefix + numClicks);
}
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("SwingApplication");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SwingApplication app = new SwingApplication();
Component contents = app.createComponents();
frame.getContentPane().add(contents, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
createAndShowGUI();
}
}
46
Link utili
http://java.sun.com/products/jfc/
http://java.sun.com/docs/books/tutorial/uiswing/
http://www.javaolympus.com/freebooks/FreeJavaSwingBooks.jsp
www.cs.uno.edu/~fred/nhText/ Resources/Slides/Chapter17.ppt
Building Graphical User Interfaces with Java
www.sce.carleton.ca/courses/ sysc-2004/w04/lectures/SYSC-200416a-Gui.ppt
Graphical User Interfaces with Java
www.csd.uwo.ca/courses/CS212a/notes/javagui.ppt
47