Interfacce grafiche Il pacchetto awt Introduzione all’awt Il supporto allo sviluppo di interfacce grafiche è fornito all’interno di un package chiamato awt: Abstract Windowing Toolkit. E’ costituito da un insieme di classi che permettono di sviluppare interfacce grafiche in maniera indipendente dalla specifica piattaforma. Struttura generale dell’awt Le classi del pacchetto awt appartengono alle seguenti categorie: Grafica: le classi che permettono di disegnare figure geometriche, di tracciare linee, di visualizzare immagini, di selezionare il tipo di carattere, di impostare i colori, ecc; Componenti: sono elementi quali pulsanti, campi di testo, menu e barre di scorrimento; Struttura generale dell’awt Layout manager: si occupa di disporre le componenti in maniera appropriata sullo schermo; Gestori di eventi: gestisce gli eventi esterni, quali la pressione di un pulsante e il movimento del mouse, attraverso l’uso di handler (gestori), listener (percettori) e adapter (adattatori); Trattamento dell’immagine: permette di gestire le immagini in formati diversi. Inserire elementi grafici in una finestra Le interfacce grafiche sono presentate all’utente per mezzo di finestre. L’awt contiene una classe Window, ma nella pratica si utilizza spesso una delle sue sottoclassi: Frame. Quindi Frame è la componente base per visualizzare gli elementi di una interfaccia grafica. Creare e visualizzare una finestra Frame f = new nomeclasse(); f.setTitle(“titolo”); f.setSize(larghezza, altezza); f.setVisible(true); Il metodo paint Si occupa di visualizzare altri elementi grafici eventualmente presenti all’interno della finestra. E’ definito nella classe Component e deve essere ridefinito nelle sottoclassi di Frame. Sintassi del metodo paint public void paint(Graphics g) { chiamate ai metodi di Graphics, utilizzando il prefisso g. } L’oggetto di tipo Graphics si adatta alla piattaforma su cui viene eseguito il programma, fornendo un’interfaccia omogenea e di aspetto familiare. La classe Graphics E’ abbastanza estesa: ClearRect (int x, int y, int larghezza, int altezza); ClipRect (int x, int y, int larghezza, int altezza); CopyArea (int x, int y, int larghezza, int altezza, int dx, int dy); draw3DRect (int x, int y, int larghezza, int altezza, boolean ripristinata); drawChars (char [] data, int offset, int lunghezza, int x, int y); drawLine (int x1, int y1, int x2, int y2 ); drawOval (int x, int y, int larghezza, int altezza); La classe Graphics drawRect drawString fill3DRect fillOval fillRect Color setColor (int x, int y, int larghezza, (String str, int x, int y); (int x, int y, int larghezza, boolean ripristinata); (int x, int y, int larghezza, (int x, int y, int larghezza, getColor(); (Color c); //più altri 33 metodi int altezza); int altezza, int altezza); int altezza); La classe Graphics Comprende metodi che permettono di disegnare rettangoli, archi, poligoni, ecc. Ad esempio: Public void paint (Graphics g) { g.drawRect(10,10,200,100); } Disegna un rettangolo con base 200 e altezza 100 a 10 punti di distanza dall’angolo superiore sinistro dello schermo. Il metodo drawString Rappresenta l’equivalente in ambiente grafico del metodo println. Ad esempio: g.drawString(“Ciao Piero”,30,15); Scrive la stringa “Ciao Piero” a 30 punti di distanza dal limite sinistro dello schermo e a 15 punti dal limite superiore dello schermo. Il metodo drawString La differenza fondamentale tra il metodo println e drawString è che si può impostare lo stile e il colore del carattere. A tale scopo esistono le classi Font e Color. La classe Font Deriva dalla classe Object. public class Font extends Object { public Font(String name, int style, int size); public final static int BOLD; // or ITALIC, PLAIN ... } name può essere “Helvetica”, “Courier”, “Dialog” o “TimesRoman”. La classe Font style può essere BOLD, ITALIC o PLAIN. size è la dimensione in pixel. Esempio: font = new Font("Helvetica", Font.BOLD, 48); La classe Color Deriva dalla classe Object. Ha delle costanti di classe come Color.black, Color.green, Color.blue ecc. Il metodo principale è il costruttore che definisce un colore in base alla percentuale di rosso, verde e blue. La classe Color public final class Color extends Object { public Color(int r, int g, int b); public Color(int rgb); public Color(float r, float g, float b); .. public final static Color pink; } Esempio: allarme antivirus1 import java.awt.*; import java.awt.event.*; public class GraphicWarning extends Frame { static private final int line=35; static private final int letter=10; public GraphicWarning(){ setBackground(Color.cyan); setForeground(Color.black);} public void paint(Graphics g){ Font f = new Font("Courier",Font.ITALIC,30); g.setFont(f); g.setColor(Color.red); g.drawRect(4*letter,2*line,50*letter,15*line); g.drawString("A T T E N Z I O N E", 11*letter, 4*line); g.setColor(Color.black); g.drawString("Possibile virus", 13*letter, 6*line); g.drawString("Riavviare ed eseguire", 10*letter, 8*line); g.drawString("un antivirus!", 14*letter, 10*line); } Esempio: allarme antivirus1 public static void main(String args[]){ Frame f= new GraphicWarning(); f.setTitle("Allarme Virus"); f.setSize(55*letter,20*line); f.setVisible(true); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){System.exit(0);} }); } } Chiusura di una finestra L’esecuzione di un programma in una finestra deve poter essere interrotta. Una possibilità è permettere all’utente di far terminare l’esecuzione del programma utilizzando il pulsante che chiude la finestra. Il clic del mouse è un evento che può essere individuato da uno dei listener contenuti nel package Event dell’awt. Chiusura di una finestra Occorre stabilire, nel metodo principale, un collegamento tra il listener e la finestra dell’applicazione invocando il metodo addWindowListener e istanziando una nuova versione di WindowAdapter in cui occorre ridefinire il metodo windowClosing facendo in modo che esegua l’azione appropriata. Sintassi: f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); Osservazioni f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); Il parametro e rappresenta l’evento, che in questo caso non viene utilizzato. La ridefinizione di WindowAdapter avviene utilizzando una classe anonima. Classi anonime Le classi anonime si chiamano così perché non hanno un nome. Possono essere istanziate una sola volta, nel punto in cui sono definite. Nel caso della chiusura di una finestra: WindowAdapter è una classe astratta che implementa l’interfaccia WindowListener. Va ridefinito il metodo windowClosing. L’istanziazione di un oggetto di tipo WindowAdapter e la ridefinizione del metodo windowClosing vengono realizzate solo quando serve e nell’istruzione del programma in cui sono utilizzate. La classe Container Le varie componenti possono essere inserite in contenitori, rappresentati dalla classe Container. La classe Container è utilizzata solo quando si comincia a ragionare su come raggruppare le diverse componenti. Le componenti Anche se versatile, non è consigliabile utilizzare la classe Graphics per gestire il testo. L’awt di Java fornisce un altro insieme di classi derivanti dalla classe Component. Tra queste, le due più semplici sono le classi Label e Button, che permettono di gestire una quantità limitata di testo. La classe Label Permette la visualizzazione di testo per mezzo di un parametro passato al suo costruttore. La sintassi: add(new Label(“Testo”)); Il metodo add è definito nella classe Container. Si aggiunge l’etichetta al contenitore di default del Frame in cui stiamo lavorando. La classe Button Ha la funzionalità aggiuntiva di essere reattiva: ovvero, è possibile fare in modo che il programma esegua una determinata azione in seguito alla pressione di un pulsante da parte dell’utente. Sintassi: private Button nomepulsante; … nomepulsante = new Button(“Testo”); add(nomepulsante); Reazione alla pressione dei pulsanti Nel package awt.event è definito un actionListener, analogo al windowListener. Quest’interfaccia ha un solo metodo che deve essere implementato: actionPerformed. Reazione alla pressione dei pulsanti1 Il collegamento viene fatto nel costruttore immediatamente dopo la dichiarazione del pulsante e la sua aggiunta al contenitore: nomepulsante = new Button(“Testo”); add(nomepulsante); nomepulsante.addActionListener(this); this indica che il frame corrente è responsabile della ridefinizione del metodo actionPerformed. Il metodo actionPerformed Ha un parametro, di tipo ActionEvent, che può essere interrogato per verificare se sia relativo a uno dei pulsanti dell’interfaccia. Ad esempio public void actionPerformed(ActionEvent e) { if (e.getSource() == nomepulsante1) { istruzioni } else if (e.getSource() == nomepulsante2) { istruzioni } } Reazione alla pressione dei pulsanti2 Il collegamento può essere fatto mediante una classe anonima associata al pulsante che implementa l’interfaccia ActionListener, che riscrive il metodo actionPerformed (come avviene nell’esempio allarme antivirus2 per i pulsanti attendi e riavvia). Ad esempio nomepulsante.addActionListener( // creazione del Listener new ActionLister() { public void actionPerformed(ActionEvent e) { istruzioni relative alla gestione dell’evento }//chiusura del metodo } //chiusura della classe anonima ); I layout manager Il loro compito è posizionare le componenti aggiunte a una finestra, adottando criteri prestabiliti per le diverse situazioni. Ad esempio, se una finestra è ridimensionata dall’utente, il layout manager cerca di sistemare le componenti contenute in tale finestra nella nuova area in modo che restino visibili. I layout manager La sintassi per specificare quale layout manager si vuole utilizzare è la seguente: setLayout(new Manager(parametri)); setLayout è la chiamata di un metodo della classe Container, la classe astratta da cui ereditano Window e quindi anche Frame. I layout manager Un esempio setLayout(new FlowLayout(FlowLayout.CENTER,horigap,vertigap)); Il primo parametro indica che i nuovi elementi aggiunti alla finestra devono essere posizionati al centro. I parametri horigap e vertigap sono costanti che indicano la distanza minima in punti, rispettivamente orizzontale e verticale, tra i diversi elementi. Tutti e tre i parametri sono facoltativi. I layout manager Java fornisce cinque layout manager. Tutti implementano l’interfaccia LayoutManager: flowLayout: dispone i componenti in sequenza; borderLayout: dispone le componenti in cinque aree di dimensione fissata, collocate alle quattro estremità della finestra e nel suo centro, in base a un parametro che può assumere i valori North, South, East, West e Center; gridLayout: dispone le componenti secondo una griglia; FlowLayout e BorderLayout GridLayout e CardLayout I layout manager cardLayout: permette di avere diversi Panel sovrapposti e di selezionare quale debba essere visualizzato per mezzo di linguette collocate all’estremità superiore del pannello. gridBagLayout: tipo di disposizione particolareggiata nella quale ciascun componente è vincolato a occupare un’area identificata da un numero esatto di punti. Benchè di difficile utilizzo, è il più versatile e portabile. Altre componenti TextComponent, insieme alle sue due sottoclassi TextArea e TextField, gestisce testo su più righe, permettendone la selezione e la modifica. Scrollbar è utile in presenza di testo e consente di muovere i contenuti di un Container nella finestra. ScrollPane è un Container che permette, se associato a una componente con un’area di dimensioni superiori alle sue, di muovere tale componente per mezzo di barre di scorrimento, in modo da renderne visibile solo una porzione per volta. Canvas è un ulteriore area grafica utilizzabile per disegnare, in modo che le parti disegnate non interferiscano con altri componenti. Altre componenti Checkbox permette selezioni del tipo sì/no. Un esempio è la selezione dello stile grassetto nella barra degli strumenti di un elaboratore di testo. Choice fornisce un elenco a discesa (detto anceh menu a tendina) da cui è possibile selezionare solo una voce per volta. List è simile a Choice, salvo che le voci sono sempre visualizzate e possono essere effettuate selezioni multiple. Altre componenti Menu permette di creare menu sull’apposita barra di una finestra, inserendo voci che vengono visualizzate a tendina. Le voci possono essere a loro volta menu. E’ possibile selezionare una sola voce alla volta e disabilitare una o più voci. PopupMenu è analogo a Menu, salvo che può essere creato in un qualsiasi punto della finestra. La classe Panel Serve per raggruppare le componenti collocate in una finestra, in modo da poterle spostare tutte insieme ed evitare che si sovrascrivano a vicenda, utilizzando sempre un layout manager. Sintassi: Panel p = new Panel() p.add(new Button(“Testo1”)); p.add(new Button(“Testo2”)); Una volta aggiunte le componenti, il Panel viene passato al layout manager come una singola entità: add(“South”,p); In questo caso, BorderLayout è il layout manager di default della classe Frame, mentre FlowLayout è quello della classe Panel. Esempio: allarme antivirus2 import java.awt.*; import java.awt.event.*; public class GraphicWarningButton1 extends Frame { static private final int line=35; static private final int letter=10; public GraphicWarningButton1(String [] message,int n){ setBackground(Color.cyan); setForeground(Color.black); setLayout(new FlowLayout(FlowLayout.CENTER,line,letter)); Font f = new Font("Helvetica",Font.ITALIC,30); setFont(f); for (int i=0;i<n;i++) add(new Label(message[i])); attendi=new Button("ATTENDI"); riavvia=new Button("RIAVVIA"); add(attendi); attendi.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){ setBackground(Color.red);setForeground(Color.white);} }); Esempio: allarme antivirus2 add(riavvia); riavvia.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){ setVisible(false);dispose();System.exit(0);} }); } public static void main(String args[]){ String[] message={"A T T E N Z I O N E","Possibile virus","Riavviare ed eseguire"," un antivirus! "}; Frame f= new GraphicWarningButton1(message,4); f.setTitle("Prova Pulsanti"); f.setSize(48*letter,10*line); f.setVisible(true); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){System.exit(0);} }); } }