Post on 01-May-2015
transcript
Gerarchie di Tipi
Metodologie di progetto
• Estensione di classi
• Implementazione di interfacce
• Composizione
Notazione UML
Relazione Simbolo Significato
Ereditarietà is-a
Implementazione is-a
Aggregazione has a
Dipendenza usa
Una struttura universitaria• Il personale è strutturato in
Personale Docente: Faculty Personale Tecnico Amministrativo: Staff
Una struttura universitaria• Introduciamo una terza categoria che
descrive le due tipologie di personale
• UnivEmployee Definisce le caratteristiche di struttura e
comportamento comuni a tutto il personale Intesa non per creare istanze proprie definiamo abstract per realizzare queste
scelte di progetto
Una struttura universitaria
UnivEmployee<abstract>
Faculty Staff
University Employees
• A tutto il personale viene garantito l’uso di posta elettronica
• Rappresentiamo mediante un metodo
• Includiamo il metodo in UnivEmployee così che venga ereditato dalle due classi derivate
/** * manda un messaggio all’oggetto su cui è invocato */ public void mailTo(String msg);
public abstract class UnivEmployee{ private List<String> mailbox = new ArrayList<String>(); public void mailTo(String msg) { mailbox.add(msg); } . . . }
public class Faculty extends UnivEmployee { . . . }
public class Staff extends UnivEmployee { . . . }
University Employees
• L’accesso alla posta elettronica è una proprietà generale
• Possiamo concettualizzare questa proprietà una interfaccia
University Employees
interface EmailInt{ public void mailTo(String msg);}
University Employees con email
UnivEmployee<abstract>
Faculty Staff
EmailInt<interface>
abstract class UnivEmployee implements EmailInt{ . . . public void mailTo(String msg) { . . . } }
class Faculty extends UnivEmployee { . . . }
class Staff extends UnivEmployee { . . . }
University Employees con email
University Employees
• Al personale docente viene inoltre garantita la possibilità di gestire una propria pagina web
• Definito solo per la classe Faculty
/** * restituisce la URL associata all’oggetto */ public Url browse();
University Employees … on the web
• Anche qui, possiamo generalizzare introducendo una nuova interfaccia
interface WebInt { public Url browse();}
UnivEmployee<abstract>
Faculty Staff
EmailInt<interface>
WebInt<interface>
University Employees … on the web
public abstract class UnivEmployee implements EmailInt{ . . . public void mailTo(String msg) { . . . } }
public class Faculty extends UnivEmployee implements WebInt{ public Url browse() { . . . } . . . }
public class Staff extends UnivEmployee { . . . }
University Employees … on the web
Gerarchie di tipi
• Ogni classe può implementare più interfacce estendere al più una classe
• I due meccanismi si possono combinare
Gerarchie di tipi
• Uno schema ricorrente
SuperClasse
Classe
Interfaccia
• Permette di utilizzare Classe come SuperClasse e Interfaccia
University Employees … on the web
• Possiamo dare struttura alla composizione di interfacce
• Estensione di interfacce no vincoli: possiamo estendere più di una interfaccia interfaccia che estende è sottotipo di tutte le
interfacce che vengono estese
interface Online extends EmailInt,WebInt { }
UnivEmployee<abstract>
Faculty Staff
EmailInt<interface>
WebInt<interface>
University Employees … on-line
OnLine<interface>
public abstract class UnivEmployee implements EmailInt { . . . public void mailTo(String msg) { . . . } }
public class Faculty extends UnivEmployee implements OnLine{ public Url browse() { . . . } . . . }
public class Staff extends UnivEmployee { . . . }
University Employees … on line
Corsi
• Il personale docente insegna uno o più corsi all’interno dei corsi di laurea
• Rappresentiamo nei diagrammi con una nuova relazione tra classi associazione
University Employees
UnivEmployee<abstract>
Faculty Staff
EmailInt<interface>
WebInt<interface>
Course
1..*
OnLine<interface>
public abstract class UnivEmployee implements EmailInt { . . . public void mailTo(String msg) { . . . } }
public class Faculty extends UnivEmployee implements OnLine{ public Url browse() { . . . } . . . private ArrayList<Course> courses; . . . }
public class Staff extends UnivEmployee { . . . }
University Employees
University Employees
• I corsi vengono gestiti dal personale tecnico amministrativo per gli aspetti relativi a iscrizione, liste di esami …
• La classe Staff dipende quindi dalla classe Course
University Employees
UnivEmployee<abstract>
Faculty Staff
EmailInt<interface>
WebInt<interface>
Course
1..*
OnLine<interface>
public abstract class UnivEmployee implements EmailInt { . . . public void mailTo(String msg) { . . . } }
public class Faculty extends UnivEmployee implements Online{ public Url browse() { . . . } . . . private ArrayList<Course> courses; . . . }
public class Staff extends UnivEmployee { public void admin(Course c) { . . . } . . . }
University Employees
Corsi … on-line
• Possiamo sfruttare la struttura in più che abbiamo ottenuto dall’introduzione delle interfacce per rappresentare ulteriori funzionalità Ad esempio, i corsi possono essere dotati di un sito
web e di un indirizzo di posta elettronica
Corsi … on-line
UnivEmployee<abstract>
Faculty Staff
EmailInt<interface>
WebInt<interface>
Course
1..*
OnLine<interface>
• Metodologie di progetto basate su estensione e composizione di classi e interfacce
• Progetto di interfacce grafiche
Eventi e Listeners
• La sorgente di un evento ispeziona la lista dei suoi listeners (registrati) seleziona tutti i listeners il cui tipo corrisponde al tipo
dell’evento. su ciascuno dei listeners selezionati, invoca il metodo
associato all’evento passandogli l’event object associato all’evento
Listeners – (alcuni) metodi
ActionListener void actionPerformed(ActionEvent)
WindowListenervoid windowActivated(WindowEvent)
void windowClosed(WindowEvent)
ListSelectionListenervoid valueChanged(ListSelectionEvent)
KeyListener void keyPressed(KeyEvent)
void keyReleased(KeyEvent)
void keyTyped(KeyEvent)
MouseMotionListenervoid mouseMoved(MouseMotionEvent)
void mouseDrag(MouseMotionEvent
MouseListener void MouseClicked(MouseEvent)
void mouseEntered(MouseEvent)
Listeners e Adapters
• Listeners : interfacce
• Adapters: classi (astratte) che implementano i listeners fornendo
implementazioni default per i metodi dichiarati dai listeners
• La nomenclatura aiuta: XEvent:
la classe associata all’evento X XListener :
l’interfaccia che i listenerers dell’evento X devono implementare XAdapter:
la classe astratta che implementa XListener con metodi default:
:
EventListener
MouseMotionListener
WindowListenerKeyListener
ListSelectionListener
MouseListener ActionListener
Listeners
:
EventListener
MouseMotionListener
WindowListenerKeyListener
ListSelectionListener
MouseListener ActionListener
KeyAdapterMouseAdapter WindowAdapter
Listeners e Adapters
Definizione di Listeners
• Implementiamo il Listener
• Estendiamo l’Adapter
class MyXAdapter extends XAdapter { // sovrascrive (alcuni de) i metodi definiti da XAdapter }
class MyXListener implements XListener { // metodi definiti da XListener }
Registrazione di Listeners
• Ogni event source ha un metodo per registrare un corrispondente listener
public void addXListener(XListener listener)
Esempio: ClickCounter
4 click Reset
Esempio: ClickCounter
• Gestione eventi: prima alternativa Il frame gestisce entrambi i pulsanti
JFrame
ClickCounter
ActionListener
Esempio: ClickCounter
JFrame
ClickCounter
ActionListener
public class ClickCount extends JFrame implements ActionListener {
int count = 0; JLabel clicks = new JLabel ("Total clicks = 0"); JButton b = new JButton ("click"); JButton r = new JButton ("reset"); . . . public ClickCount() { . . . b.addActionListener(this); r.addActionListener(this); } . . . public void actionPerformed( ActionEvent e ) { if (e.getSource() == b) count++; else if (e.getSource() == r) count = 0; clicks.setText("Total clicks = " + count); }}
Esempio: ClickCounter
• Gestione eventi: seconda alternativa I pulsanti gestiscono gli eventi autonomamente
JFrame
ClickCounter
ActionListener
ActionListener2
Esempio: ClickCounter
public class ClickCount extends JFrame { . . . public ClickCount() { . . . b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { count++; clicks.setText("Total clicks = " + count);
}}); r.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { count = 0; clicks.setText("Total clicks = " + count);
}}); } . . . }
Domande
• Come disponiamo due pulsanti allineati sul lato inferiore di un frame?
• Come disponiamo tre pulsanti uno sopra l’altro?
Risposte
• Prima le aggiungiamo ad un pannello (con FlowLayout) e poi aggiungiamo il pannello all’are sud del frame.
• Li disponiamo dentro un panello con GridLayout contenente tre righe ed una colonna
Esempio – EventFrame
• Una finestra che cattura e traccia un insieme di eventi del mouse
EventFrame – costruttore
import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.util.*;
/** EventFrame: traccia eventi di vario genere **/
class EventFrame extends JFrame { /** * Costruisce il Frame principale con le varie componenti */
public EventFrame() {
EventFrame – costruttore
// Labels e TextFields per tracciare gli eventi JPanel eventFields = new JPanel(new BorderLayout()); Panel labels = new JPanel(new GridLayout(events.length,1)); JPanel traces = new JPanel(new GridLayout(events.length,1)); for (int i = 0; i < events.length; i++) {
labels.add(events[i].label); traces.add(events[i].trace);
} eventFields.add(labels,BorderLayout.WEST); eventFields.add(traces,BorderLayout.CENTER);
EventFrame – costruttore
// Pulsanti JPanel buttons = new JPanel(new GridLayout(2,1)); buttons.add(new EventButton(Color.blue)); buttons.add(new EventButton(Color.red));
// Completa il layout setLayout(new GridLayout(1,2)); add(eventFields); add(buttons); }
Progetto dei Listeners
:
EventTracer
MouseMotionListenerMouseListener
Actiontracer
ActionListener
MouseTracer MouseMotionTracer
Classi interne – EventTracer
private class EventTracer { /** * Costruisce il messaggio da visualizzare in risposta a * ciascun evento (sul campo testo corrispondente) * Overloade sul tipo dell'evento */ public void trace(int field, ActionEvent e) { // messaggio = numero di action events fino ad ora actionEvents++; displayMessage(field, "Event n. " + actionEvents);}
Classi interne – EventTracer
public void trace(int field, MouseEvent e ) { // messaggio = pulsante@(x,y), numero di click consecutivi int mod = e.getModifiers(); String btn = "none"; if ( mod == 16 ) btn = "left"; else if (mod == 8 ) btn = "center"; else if (mod == 4 ) btn = "right"; displayMessage(field, btn + //
"@(" + e.getX() + "," + e.getY() +")" + ", Clicks = " + e.getClickCount()); }
Classi interne – Listeners
class ActionTracer extends EventTracer implements ActionListener { public void actionPerformed(ActionEvent e) {
trace(ACTION, e); }ActionTracer(Color col) { super(col); }
}
Classi interne – Listeners
class MouseTracer extends EventTracer implements MouseListener {
public void mouseClicked(MouseEvent e) { trace(MOUSE_CLICKED, e);}public void mouseEntered(MouseEvent e) { trace(MOUSE_ENTERED, e);}public void mouseExited(MouseEvent e) { trace(MOUSE_EXITED, e);}public void mousePressed(MouseEvent e) { trace(MOUSE_PRESSED, e); }public void mouseReleased(MouseEvent e) { trace(MOUSE_RELEASED, e);}MouseTracer(Color col) { super(col); }
}
Classi interne – Listeners
class MouseMotionTracer extends EventTracer implements MouseMotionListener {
public void mouseDragged(MouseEvent e) { trace(MOUSE_DRAGGED, e); }public void mouseMoved(MouseEvent e) { trace(MOUSE_MOVED, e);}MouseMotionTracer(Color col) { super(col); }
}
Classi interne – Pulsanti
/** * Aree di tracciamento, definite come pulsanti * Registrano listeners per tutti gli eventi da tracciare */ class EventButton extends JButton {
EventButton(Color c) { setBackground(c); addActionListener( new ActionTracer(c) ); addMouseListener( new MouseTracer(c) ); addMouseMotionListener( new MouseMotionTracer(c) );}
}} // Conclude EventFrame
Esempio – Puzzle
• Forniamo una interfaccia grafica per il Puzzle che realizza il “gioco del 15”
Ricordiamo – PuzzleBoard
• Nella costruzione dell’applicazione, la classe PuzzleBoard funge da back-end
• L’interfaccia grafica si limita in sostanza a fornire metodi di interazioni con il back-end
PuzzleBoard
public class PuzzleBoard { /** costruisce una tabella con dimensione size */ public PuzzleBoard(int size) { . . . }
/** il valore contenuto nella posizione (x,y) * -1 se la posizione è vuota */ public int val(int x, int y) { . . . }
/** muove il pezzo che porta il numero w se questo * è in posizione adiacente alla posizione vuota */ public boolean move(int w) { . . . }
/** true se la configurazione corrente è di successo */ public boolean win() { . . . }}
PuzzleFrame – struttura
import java.awt.*; import java.awt.event.*; import javax.swing.*;
class PuzzleFrame extends JFrame {
// back-end private PuzzleBoard board;
// dimensione del puzzle private int size;
// i pezzi sull'interfaccia. Ciascun PuzzleButton è // associato alla corrispondente posizione sul backend private PuzzleButton[][] button;
PuzzleFrame – costruttore
/** costruisce la tabella grafica a partire dalla * tabella b che costituisce il back-end */ public PuzzleFrame(int board_size, PuzzleBoard b) {
size = board_size; board = b;button = new PuzzleButton[size][size];setLayout(new GridLayout(size, size));// crea i pulsanti associati ai pezzi e disponifor ( int i = 0; i != size; i = i+1 ) { for ( int j = 0; j != size; j = j+1 )
{ button[i][j] = new PuzzleButton(); add(button[i][j]);
} }// inizializza pulsanti con i loro numeri display();
}
PuzzleFrame – refresh
/** ridisegna la tabella dopo una mossa **/ private void display() {
// ridisegna i numeri sui pulsantifor ( int i = 0; i != size; i = i+1 ) { for ( int j = 0; j != size; j = j+1 ) {
if ( board.val(i,j) >= 0 ) { button[i][j].setBackground(Color.white); button[i][j].setText("" + board.val(i,j)); }
else { button[i][j].setBackground(Color.black); button[i][j].setText( "" );}
} }
PuzzleFrame – refresh
if (board.win()) { int response =
JOptionPane.showConfirmDialog(this, "Done! Play again?"); switch (response) { case JOptionPane.YES_OPTION : board = new PuzzleBoard(size);
display(); break; case JOptionPane.CANCEL_OPTION : break; default: System.exit(0); }
} } // chiude il metodo display()
PuzzleFrame – gestione pulsanti
/** classe interna: controllore dei pulsanti */ class PuzzleButton extends JButton implements ActionListener {
public PuzzleButton( ){ // numero del pulsante deciso da display()
super(""); addActionListener(this);}
public void actionPerformed(ActionEvent evt) { // prendi il numero di questo pulsante String s = getText(); if ( !s.equals("") ) {
// non è il pulsante vuotoboolean ok = board.move(Integer.parseInt(s)); if ( ok ) { display(); }
}}
}
Componenti Swing
• Molte
• … sicuramente troppe per questo corso
• Consultate le API