appunti java – Capitolo 8 pag. 1 8. GUI : Graphics User Interface Un linguaggio ad oggetti ha come obiettivo principale quello di fornire al programmatore classi per la gestione di ambienti grafici a finestre. Se fino a questo momento ci si è occupati di sintassi e di fondamenti introduttivi di Java, cercando di dare solidità ai concetti di Classe, Metodi, Ereditarietà, ora entreremo nel vivo della programmazione di interfacce grafiche GUI. Si affronteranno due ordini di problemi: primo con quali componenti e come costruire una interfaccia grafica, secondo come gestire gli eventi del mouse, della tastiera ecc. che consentono ad un programma di funzionare. Se la programmazione imperativa con ForTran, Pascal o c si occupava quasi esclusivamente di algoritmi per risolvere problemi di calcolo e solo in modo rudimentale di interfacce di input e output rivolte all'utente, con Java il "peso" o "quantità di codice" dedicata all'interfaccia utente diviene molto importante e ad esso è necessario dedicare un capitolo introduttivo metodologico. Il primo passo consiste nella scelta del Package di Java da utilizzare per costruire interfacce grafiche. Con le versioni del jdk (java development kit) 1.0, 1.1 java consentiva la costruzione di GUI usando i componenti grafici del package java.awt. (abstract window toolkit). Con la versione 1.2 e soprattutto la 1.3 ad awt si è aggiunto il package javax.swing. a cui faremo riferimento prevalente. L'orientamento di usare il package swing è dovuto al fatto che questo permette di generare oggetti grafici molto più raffinati rispetto ai corrispondenti dell'awt, oggetti sostanzialmente identici ai componenti grafici di Windows Microsoft e agli ambienti XWindow di Unix. 8.1. La gerarchia di classi grafiche Se si esplora la documentazione awt e swing (come esercizio è opportuno sfogliarla più volte per acquisire famigliarità con le sue classi) si nota immediatamente una lunga sequenza di classi. Analizzando solo quelle principali, possiamo distinguere alcune entità grafiche famigliari a chi usa un computer: FINESTRE : simili o identiche a quelle di Windows, la classe Frame (awt) e la JFrame (swing). PULSANTI : con o senza icona, la classe Button (awt) e la JButton (swing). CAMPI di TESTO : la classi TextField, TextArea (awt) e le JTextField, JTextArea del package swing. I legami di ereditarietà tra le classi principali di awt e swing sono schematizzati nella tabella della pagina successiva. appunti java – Capitolo 8 pag. 2 Dalla gerarchia di classi si nota che i due packages awt e swing hanno una relazione. In swing esistono due tipi di Container di alto livello "Top Level Container" che sono rispettivamente JFrame e JDialog indispensabili per aggiungere componenti e costruire la GUI di un'applicazione Java. Tutti gli altri componenti grafici discendono da JComponent figlio di Component e Container dell'awt. Il significato di questa discendenza da JComponent implica che qualunque oggetto grafico ha la caratteristica di essere sia un Component che un Container, ovvero può contenere o essere contenuto in oggetti di tipo JComponent. Ne consegue per esempio che un JButton può contenere un JtextField anche se questa possibilità non è molto utile. Si sono indicate con sfondo grigio le classi che si impareranno ad usare in questo capitolo, rimandando alle applicazioni o a successivi esempi l'uso di altre Classi. Appreso il metodo di costruzione di una GUI lo si potrà facilmente estendere ai diversi componenti indicati nella gerarchia. appunti java – Capitolo 8 8.1.1. pag. 3 Costruzione di GUI Qualsiasi GUI per quanto banale si "appoggia" sempre su una finestra di Windows ecco come crearla usando JFrame di swing. La classe JFrame (vedi manuale) ha diversi costruttori e alcuni metodi essenziali : Nome Campi o attributi Costruttori JFrame Vedi documentazione Identificatori: Invocazione: Effetti: Metodi Identificatore Invocazione: Effetti:: Pckage e Gerarchia javax.swing Sono molteplici e (protected) inacessibili all’utilizzatore. JFrame( ); JFrame( String titolo ); JFrame f=new JFrame( ); JFrame f=new JFrame("titolo"); Crea un oggetto JFrame identificato da f senza nessun titolo o con titolo. void setSize(int larga, int alta); void setBounds(int x, int y, int larga, int alta); void setVisible(boolean bo); void setDefaultCloseOperation(int operaz); f.setSize(200, 100); f.setBounds(20,50, 200, 100); f.setVisible(true); f.setDefaultCloseOperation(Jframe.DISPOSE_O N_CLOSE); il primo metodo dimensiona la finestra collocandola con l'angolo alto a sinistra nel punto di coordinate schermo (0,0) con larghezza di 200 pixel e altezza di 100. Il secondo metodo colloca l'angolo alto a sinistra della finestra nel punto di coordinate schermo (20,50) mantenendo larghezza e altezza di 200 e 100 pixel. Il terzo rende visibile la finestra. Se non si invoca questo metodo la finestra rimane "invisibile" ma allocata correttamente in memoria. Il quarto attiva l'ascoltatore di eventi riferito alla chiusura della finestra. I parametri ammessi sono i segunti: DISPOSE_ON_CLOSE, HIDE_ON_CLOSE, DO_NOTHING_ON_CLOSE, EXIT_ON_CLOSE. Il primo distrugge la frame in memoria ma non interrompe il programma. Il secondo nasconde la finestra senza distruggerla. Il terzo disabilita la chiusura; il click non chiude. Il quarto (solo con jdk1.3) chiude correttamente il processo Java. java.awt.Object java.awt.Component java.awt.Container java.awt.Window java.awt.Frame java.swing.JFrame appunti java – Capitolo 8 pag. 4 esempio 1: "creare una finestra di Windows di dimensione 300x200 e posizionarla alle coordinate 100,100". Codice: Esecuzione: Commenti: Si nota che facendo click sul pulsante di chiusura la finestra scompare ma il programma non termina; infatti nella barra di stato della finestra di RealJava compare la scritta "External process in progress". Per chiudere la finestra di esecuzione del processo si deve cliccare sul pulsante "stop" della finestra di output dell'editor. Questa non è una modalità corretta per interrompere l'esecuzione di un programma, è necessario indicare esplicitamente che l'evento "clik" sul pulsante di chiusura deve interrompere il programma Java. Questo lo si ottiene con la costante EXIT_ON_CLOSE (attivo solo nella versione 1.3 del jdk). L'esempio mostrato è piuttosto banale ma evidenzia la semplicità con la quale si può generare un oggetto finestra con tutte le caratteristiche grafiche del sistema Windows e che si comporta (ridimensionamento, riduzione ad icona e chiusura programma) come la finestra di un'applicazione professionale. appunti java – Capitolo 8 pag. 5 Quando la GUI si complica, anche di poco, è opportuno che il programma principale non esegua tutte le azioni desiderate ma sia soltanto il punto di avvio da cui lanciare l'applicazione e che tutto sia rimandato ad una apposita classe, sottoclasse di JFrame, che con i metodi opportuni esegua quanto desiderato dall'utente. Il precedente programma sarebbe metodologicamente più corretto se codificato come sottoclasse di JFrame. esempio 2. "codificare l'apertura di una finestra come quella dell'esempio 1 utilizzando una sottoclasse di JFrame." Codifica: Commenti: Il grafo ad albero mostra la dipendenza gerarchica dei metodi invocati: super() main() cap08_es_02() disegna_frame() gestisci_eventi() La prima cosa da notare è che il main() invoca soltanto il costruttore della classe cap08_es_02(). Tutto è rimandato al metodo costruttore; questo invoca in sequenza (1) super() costruttore della classe genitrice Jframe che alloca la finestra; (2) disegna_frame() che si occupa della costruzione della finestra grafica con tutti i componenti necessari; (3) gestisci_eventi() che gestisce in modo elementare l'evento di chiusura della Frame. Questa struttura gerarchica sarà mantenuta anche per tutti i programmi successivi per dare ordine logico al programma che si intende realizzare. Nel costruttore saranno pertanto sempre presenti i metodi disegna_Frame e gestione_Eventi. La nota (0) mostra la parola chiave extends che consente di dichiarare una sottoclasse di Jframe. Il contrutto è stato illustrato anche nel precedente capitolo che trattava l'ereditarietà. appunti java – Capitolo 8 pag. 6 La nota (4) mostra l'attivazione di un metodo di Jframe, non usato nel primo esempio. Questo ha lo scopo di impedire che l'utente ridimensioni la finestra. Evidentemente tale metodo non è necessario invocarlo se si desidera mantenere il ridimensionamento della finestra del programma. Eseguendo il programma si nota che la frame disegnata in questo caso non dispone dei pulsanti di ridimensionamento e riduzione ad icona. esempio 3: "Aggiungere alla GUI dell'esempio 2 un campo di input dei dati di tipo JtextField". Come prima operazione è necessario consultare la documentazione on line per sapere come si crea un JtextField (costruttori) e di quali metodi essenziali è dotato: Nome Campi o attributi Costruttori JTextField Vedi documentazione Identificatori: Invocazione: Effetti: Metodi Identificatore Invocazione: Pckage e Gerarchia Effetti:: javax.swing Sono molteplici e (protected) inacessibili all’utilizzatore. JTextField( ); JTextField( String testo ); JTextField t=new JTextField( ); JTextField t=new JTextField("default"); Crea un oggetto JTextField identificato da t senza nessun testo di default o con testo. Tutti i metodi relativi ai Component come: void setBounds(int x, int y, int larga, int alta); t.setBounds(20,50, 80, 20); il metodo dimensiona e posiziona il campo. java.awt.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.JTextComponent javax.swing.JTextField Codifica: import javax.swing.*; import java.awt.*; // (0) class cap08_es_03 extends JFrame { JTextField testo=new JTextField(); // (1) costruttore di JtextField public cap08_es_03() { super("esempio_3"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setBounds(100,100,300,200); Container cpane=getContentPane(); cpane.setLayout(null); testo.setBounds(50,50,60,20); cpane.add(testo); setResizable(false); setVisible(true); } // // // // (2) (3) (4) metodo di tutti i Component (5) metodo di tutti i Container appunti java – Capitolo 8 pag. 7 public void gestisci_eventi() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String args[]) { cap08_es_03 Mio_prg=new cap08_es_03(); } } Esecuzione: Commenti: La nota (0) indica come si importa il package awt per consentire all'istruzione della riga (2) di utilizzare un oggetto Container che non è contenuto in swing. La nota (1) evidenzia che nella sezione "Attribiti" della classe vengono sempre definiti e creati tutti i componenti grafici che si useranno, in questo caso solo un JtextField. La nota (2) evidenzia il metodo getContentPane() con il quale si acquisisce dalla Jframe creata il suo pannello dei contenuti. Questo non è altro che un oggetto di tipo Container. Questa acquisizione è sempre necessaria per applicare al pannello della Frame i componenti grafici da disegnare. Nella successiva istruzione (3) si dichiara che il layout deve essere null per consentire di utilizzare coordinate assolute di posizionamento degli oggetti. La (4) definisce la posizione dell'angolo in alto a sinistra e dimensiona il campo di testo creato. Infine la (5) addiziona al pannello della frame il campo. Le altre istruzioni rimangono inalterate rispetto all'esempio due. esempio 4: "Aggiungere alla GUI dell'esempio 3 un'etichetta di descrizione del campo di input e un secondo campo per i dati di input. Inserire quindi un pulsante e un pulsante con icona". Come prima operazione è necessario consultare la documentazione on line per sapere come si crea un'etichetta JLabel (costruttori) e un Jbutton con o senza icona e individuare i metodi essenziali di cui i due oggetti sono dotati: Nome Campi o attributi Costruttori JLabel Vedi document. Identificatori: Invocazione: JLabel( ); JLabel( String testo ); JLabel( Image icon ); JLabel lb=new Jlabel ("Input: "); JLabel lb =new JLabel (icon) appunti java – Capitolo 8 Effetti: Metodi Identificatore Pckage e Gerarchia javax.swing Nome Campi o attributi Costruttori JButton Vedi document. Identificatori: Invocazione: Effetti: Metodi Identificatore Pckage e Gerarchia javax.swing pag. 8 Crea un oggetto JLabel identificato da lb con la scritta "Input: ", la seconda con un'icona. Tutti i metodi relativi ai Component Vedi documentazione. java.awt.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.JLabel JButton( ); JButton( String testo ); JButton( Image icon ); JButton bt=new JButton ("Esegui"); JButton bt =new JButton (icon) Crea un oggetto JButton identificato da bt con la scritta "Esegui", la seconda con un'icona. Tutti i metodi relativi ai Component Vedi documentazione. java.awt.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.AbstractButton javax.swing. Jbutton Codifica: import javax.swing.*; import java.awt.*; class cap08_es_04 extends JFrame { JTextField testo_1=new JTextField(); JTextField testo_2=new JTextField(); JLabel etic=new JLabel("input:"); JButton but_1=new JButton("Esegui"); Icon ico=new ImageIcon("grillo.gif"); JButton but_2=new JButton(ico); // // // // // nuovi nuovi nuovi nuovi nuovi componenti componenti componenti componenti componenti // // // // // // // // nuovi posizionamenti nuovi posizionamenti nuovi posizionamenti nuovi posizionamenti nuovi posizionamenti aggiunta al panel aggiunta al panel aggiunta al panel public cap08_es_04() { super("esempio_4"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setBounds(100,100,280,200); Container cpane=getContentPane(); cpane.setLayout(null); etic.setBounds(30,20,60,20); testo_1.setBounds(80,20,80,20); testo_2.setBounds(170,20,80,20); but_1.setBounds(80,60,80,80); but_2.setBounds(170,60,80,80); cpane.add(etic); cpane.add(testo_1); cpane.add(testo_2); appunti java – Capitolo 8 pag. 9 cpane.add(but_1); // aggiunta al panel cpane.add(but_2); // aggiunta al panel setResizable(false); setVisible(true); } public void gestisci_eventi() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String args[]) { cap08_es_04 Mio_prg=new cap08_es_04(); } } Esecuzione: eseguendo il programma si ottiene la finerstra seguente: Commenti: 8.1.2. Lo schema con il quale si disegna la GUI si ripete arricchito di tutti i componenti desiderati. I campi consentono l'immissione di dati; i pulsanti, se cliccati, mostrano il loro effetto dinamico ma non succede nulla. La GUI non basta per ottenere un programma, è necessario gestire gli eventi relativi all'invio dei dati (tasto Return) o relativi al click dei pulsanti. Il prossimo paragrafo completerà questa parte fondamentale della trattazione per trasformare una "bella interfaccia grafica" in una GUI funzionante guidata dagli eventi.Gestione degli eventi In questo paragrafo si cercherà di approfondire il significato della parola evento, strettamente legata alla programmazione grafica e ai linguaggi ad oggetti. Si completerà la costruzione di una GUI con la gestione degli eventi che consentirà finalmente, ad un programma, di sortire risultati concreti in un "ambiente grafico" gradevole. Un evento può essere, per esempio, uno dei seguenti fatti: La pressione di un tasto della tastiera (esempio Return); Il click del mouse eseguito dall'utente su un componente grafico; Il movimento del mouse su un componente ecc. In ambiente java ogni componente grafico (detto observable) non compie azioni proprie ma si limita a "notificare" ad un proprio oggetto ascoltatore (detto observer) che un certo evento ha avuto luogo. Sarà l'ascoltatore che avrà il appunti java – Capitolo 8 pag. 10 compito di eseguire le azioni desiderate dal programmatore. Lo schema che segue ha una validità generale e mostra che ogni observable può essere dotato di uno o più observer con questo compito. In generale nella gestione degli eventi sono convolte tre entità che sono classi o interfacce : una entità Oserbvable (un Button, una Frame, un TextField ecc.) una entità Event (ActionEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, MouseMotionEvent) una entità Observer (ActionListener, WindowListener, FocusListener, KeyListener, MouseListener, MouseMotionListener) Event Observable getEvent() Observer listener Vector actionPerformed(Event) addListener(Observer) Un oggetto Observable è un’entità nota e utilizzata anche nel precedente paragrafo, si tratta di uno qualsiasi dei componenti grafici di una GUI; gli eventi invece sono noti solo intuitivamente. Un evento è una Classe che appartiene a una delle due categorie seguenti: Evento di basso livello, Evento di Semantica. Gli Eventi di basso livello, contenuti nel package java.awt.event, sono rappresentati dalla seguente gerarchia grafica: WindowEvent KeyEvent ComponentEvent InputEvent MouseEvent FocusEvent Queste classi di eventi definiscono le interazioni dell'utente riferite al sistema delle Finestre; ad esempio WindowEvent è l'insieme delle azioni del mouse sui pulsanti di una finestra di Window, pulsanti che si trovano in alto a destra e che effettuano la chiusura, il ridimensionamento e la riduzione ad icona. FocusEvent si riferisce alle azioni di selezione che danno o tolgono il "fuoco" ad un componente grafico. Se si usa il tasto di tabulazione (o il mouse) il Fuoco può essere spostato da un componente all'altro di una Frame, l'evento di attivazione o disattivazione del fuoco sul componente (FocusGained, FocusLost) può essere catturato e gestito. KeyEvent raggruppa gli eventi prodotti dalla tastiera su un componente (pressione di un tasto) quando il fuoco é attivo su di esso. Per esempio il tasto Enter (o altro) quando il cursore è contenuto in un TextField. MauseEvent riunisce tutti gli eventi del mouse riferiti a un componente grafico; per esempio MouseClicked, MouseEntered, MouseExited, MouseDragged ecc. appunti java – Capitolo 8 pag. 11 Gli Eventi di Semantica si occupano dei dettagli di significato dell'azione che ha avuto luogo. Si riferiscono ad eventi che esigono sempre l'esecuzione di una specifica azione associata. Gli eventi sono contenuti nel package ActionEvent AdjustemenEvent java.awt.event. Supponiamo che su una finestra grafica ci siano tre Button e che ognuno di questi, se premuto, debba eseguire una particolare azione, non è più sufficiente sapere che è avvenuto un MouseClicked ma si deve individuare contemporaneamente su quale Button è avvenuto e quindi quale azione attivare. Se sulla Frame é presente un componente "barra di scorrimento" e si trascina il suo cursore (AdjistementEvent) è necessario valutare il valore di questo scorrimento ed eseguire l'attività conseguente. Observer Gli ascoltatori (Observer) assumono il nome di Listener e non sono classi ma Interfacce di Java. Una interfaccia è simile ad una classe astratta, e quindi pur definendo metodi opportuni, non ne implementa nessuno. Ne consegue che questi non possono essere utilizzati se non vengono prima implementati dal programmatore. Il programmatore utilizza un’interfaccia ha l'obbligo di ridefinire tutti i metodi previsti in essa. Una classe di Java può avere una sola classe genitrice (Astratta o Concreta) infatti il linguaggio non ammette ereditarietà multipla; viceversa può "implementare" molte Interfacce. L'interfaccia ha quindi anche la funzione di "simulare" l'ereditarietà multipla in Java. Gli ascoltatori (Interfacce) possono essere implementati dai diversi componenti grafici per "ascoltare" le diverse classi di Eventi. pag. 12 appunti java WindowListener (può essere associato a una JFrame) FocusListener (può essere associato a qualsiasi JComponent) KeyListener (può essere associato a qualsiasi JComponent) MouseListener (può essere associato a qualsiasi JComponent) MouseMotionListener (può essere associato a qualsiasi JComponent) ActionListener (associato alla cattura di eventi semantici. Es su JButton) Più in concreto, a una Jframe (è un Component) si possono associare, per esempio, due tipologie di ascoltatori (observer): MouseListener che "ascoltano" solo gli eventi di pressione dei tasti del mouse e MouseMotionListener che "catturano" i click, il movimento e la posizione del mouse sull’oggetto. Più correttamente Jframe può implementare le due Interfacce MouseListener e MouseMotionListener secondo lo schema: MouseListener mouseClicked (MouseEvent) mouseEntered (MouseEvent) mouseExited (MouseEvent) JFrame MouseEvent addMouseListener(MouseListener) addMouseMotionListener(MouseMotionListener) getClickCount(): int getX(): int getY(): int MouseMotionListener mouseDragged (MouseEvent) mouseMoved (MouseEvent) Ai componenti JTextField si possono associare le tipologie di ascoltatori FocusListener che cattura gli eventiti di focalizzazione degli oggetti e KeyListener che cattura l'evento relativo alla pressione dei tasti. FocusListener focusGained (FocusEvent) focusLost (FocusEvent) JTextField FocusEvent addFocusListener(FocusListener) addKeyListener(KeyListener) KeyEvent KeyListener keyPressed (KeyEvent) keyReleased (KeyEvent) pag. 13 appunti java Ai pulsanti JButton si associano di norma ascoltatori di eventi semantici ActionListener che rilevano in particolare il click sul pulsante e consentono di individuare quale sia il Button che ha subito il click e quindi quale azione svolgere. ActionEvent getActionCommand(): String ActionListener JButton actionPerformed(ActionEvent) addActionListener(ActrionListener) Ogni Interfaccia Listener cattura solo il gruppo di eventi suoi propri come evidenzia lo schema: Ascoltatore WindowListener Eventi catturati windowClosed windowOpened windowCloseng windowIconified windowDeiconified windowActived windowDeactived MouseListener mouseClicked mousePressed mouseReleased mouseExited mouseEntered MouseMotionListener mouseDragged mouseMoved FocusListener focusLost focusGained Keylistener keyPressed keyReleased keyTyped ActionListener actionPerformed Gli esempi che si svilupperanno nei prossimo paragrafi renderanno più chiari questi schemi teorici e consentiranno di comprendere il meccanismo di associazione Observable-Observer. 8.1.1. Esempi di programmi con GUI ad aventi Eventi di basso livello windowListener pag. 14 appunti java Realizziamo un semplice programma che mostri in quali e quanti modi diversi può essere gestita la chiusura di una JFrame. I tre esempi che seguono mostrano tutti la stessa finestra vuota che ha l’evento di interruzione del programma (windowClosing) funzionante. Tale evento si attiva quando si “clicca” sul pulsante in alto a destra della Frame come da figura: esempio 5_UNO: "realizzare una finestra che si chiuda correttamente quando l'utente esegue il click sul pulsante di chiusura." Codifica: import javax.swing.*; import java.awt.event.*; public class cap08_es_05UNO extends JFrame public cap08_es_05UNO(){ super("es_5_UNO"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setSize(300,100); setVisible(true); } { // gruppo di costruzione FRAME public void gestisci_eventi() { // Gruppo di gestione eventi: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Metodo rapido } // di chiusura senza possibilità di GESTIONE. public static void main(String args[]) { cap08_es_05UNO c=new cap08_es_05UNO(); } } NUTA: il metodo indicato per gestire il click di chiusura (in grassetto nel codice) non è sempre accettabile. Infatti se nella Frame si sta gestendo un'applicazione che esige il salvataggio del lavoro modificato, questa gestione "banale" non consentirebbe, ed esempio, di segnalare all'utente che si sta chiudendo il programma senza salvare. Di seguito indichiamo due modalità che consentono anche di eseguire una "routine" prima dell'abbandono dell'applicazione all'atto dell'invocazione dell'evento chiusura. esempio 5_DUE: "realizzare una finestra che si chiuda correttamente quando l'utente esegue il click sul pulsante di chiusura. " Codifica: import javax.swing.*; import java.awt.event.*; public class cap08_es_05DUE extends JFrame implements WindowListener { // (1) // implements WindowLintener è l'INTERFACCIA di ASCOLTO EVENTI WINDOW public cap08_es_05DUE(){ super("es_5_DUE"); disegna_frame(); pag. 15 appunti java gestisci_eventi(); } public void disegna_frame() { setSize(300,100); setVisible(true); } public void gestisci_eventi() { addWindowListener(this); } // Istruzione che ASSOCIA // l'ASCOLTATORE alla JFrame (2) /* = (3) tutti gli eventi WINDOW DEVONO essere ridefiniti, al più VUOTI == */ public void windowActivated(WindowEvent ev) {} public void windowOpened(WindowEvent ev) {} public void windowClosed(WindowEvent ev) {} public void windowClosing(WindowEvent ev) { System.exit(0); // UNICO EVENTO che produce effetti } // Si potrebbe inserire qui il codice di gestione. (4) public void windowIconified(WindowEvent ev) {} public void windowDeiconified(WindowEvent ev) {} public void windowDeactivated(WindowEvent ev) {} /* =================================================================== */ public static void main(String args[]) { cap08_es_05DUE c=new cap08_es_05DUE(); } } Commento al codice: Le note (1) e (2) mostrano come si debba fare per associare alla JFrame un ascoltatore di eventi. La (1) mostra che è necessario implemetare l'interfaccia WindowListener nel programma, la (2) come si dichiara l'associazione dell'ascoltatore degli eventi alla JFrame. Una interfaccia, come si è visto nel precedente paragrafo, è una classe astratta che definisce tutti i metodi ma non li implementa. Spetta al programmatore implementare con il codice opportuno tutti i metodi definiti in essa. Come si vede nelle istruzioni comprese nella nota (3) gli eventi definiti nell'interfaccia WindowListener sono SETTE e devono essere ridefiniti (implementati tutti) nel codice del programma, al più VUOTI. Nel caso del nostro programma si vuole eseguire la sola chiusura della Frame e per far questo è sufficiente l'invocazione (4) dell'istruzione System.exit(0). All'interno di questo metodo potrebbe essere inserito il codice che avvisa l'utente che il programma sta per essere chiuso e che è opportuno salvare il lavoro. Questa necessità non poteva essere soddisfatta dalla chiusura "banale" del primo esempio. esempio 5_TER: "realizzare una finestra che si chiuda correttamente quando l'utente esegue il click sul pulsante di chiusura." Codifica: import import import public java.awt.*; java.awt.event.*; javax.swing.*; class cap08_es_05TER extends JFrame { appunti java pag. 16 public cap08_es_05TER(){ super("es_5_TER"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setSize(300,100); setVisible(true); } public void gestisci_eventi() { // Gruppo di gestione eventi: WindowAdapter wa=new ascoltaWindow(); // (1) l'ADATTATORE consente di this.addWindowListener(wa); // (2) gestire i soli EVENTI // desiderati. In questo esempio SOLO WindowClosing } /* ==================================================================== */ public class ascoltaWindow extends WindowAdapter { // (3)la classe ADATTATORE public void windowClosing(WindowEvent ev) { // (4) UNICO EVENTO System.exit(0); // windowClosing. } // Si potrebbe inserire qui il codice di gestione. } /* ==================================================================== */ public static void main(String args[]) { cap08_es_05TER c=new cap08_es_05TER(); } } Commento al codice: A differenza dell'esempio due, questo si limita ad associare alla JFrame il solo evento che si desidera ASCOLTARE. Questa metodologia sarà quella che adotteremo in quanto è completa rispetto all'esempio UNO ed è più efficiente e meno prolissa di quella dell'esempio DUE. Le note (1) e (2) mostrano che è indispensabile creare una sottoclasse di nome ascoltaWindow() della classe astratta WindowAdapter e associare tale classe alla JFrame. Le note (3) e (4) mostrano come si implementa la sottoclasse di WindowAdapter ascoltaWindow() e come al suo interno venga gestito il solo metodo windowClosing() che interessa in questo contesto. Eventi di basso livello MouseListener Il movimento del mouse, la sua pressione o rilascio possono essere gestiti in modo analogo a quanto visto per gli eventi WindowListener. esempio 6_UNO: "realizzare una finestra che segnali l'ingresso o l'uscita del mouse da essa e stampi un messaggio opportuno: <il mouse è ENTRATO> o <USCITO>". Richiesta: utilizzare l'interfaccia WindowListener per la chiusura frame e Mouse Listener per gli eventi mouse (con la metodologia dell'esempio 5_DUE). Codifica: import javax.swing.*; import java.awt.event.*; import java.awt.*; class cap08_es_06UNO extends JFrame implements WindowListener, MouseListener { //(1) Si implementano DUE INTEFACCE ASCOLTATRICI di gruppi di EVENTI DISTINTI. String msg="Il mouse è "; // (2) parte costante del messaggio. JLabel etic=new JLabel(msg+" nella posizione INIZIALE"); // (3) etichetta di output con parte variabile appunti java public cap08_es_06UNO() { super("es_6_UNO"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setBounds(100,100,250,150); Container cpane=getContentPane(); cpane.setLayout(null); etic.setBounds(30,20,250,20); cpane.add(etic); setResizable(false); setVisible(true); } public void gestisci_eventi() { addWindowListener(this); // (a) associa a Jframe addMouseListener(this); // (b) associa a Jframe } pag. 17 WindowListener MouseListener /* ==(4) tutti gli eventi WINDOW devono essere ridefiniti, al più VUOTI === */ public void windowActivated(WindowEvent ev) {} public void windowOpened(WindowEvent ev) {} public void windowClosed(WindowEvent ev) {} public void windowClosing(WindowEvent ev) { System.exit(0); } // UNICO gestito. public void windowIconified(WindowEvent ev) {} public void windowDeiconified(WindowEvent ev) {} public void windowDeactivated(WindowEvent ev) {} /* ======================================================================= */ /* ==(5) tutti gli eventi MOUSE devono essere ridefiniti, al più VUOTI === */ public void mouseEntered(MouseEvent ev) { // ENTERED GESTITO etic.setText(msg+"ENTRATO"); } public void mouseExited(MouseEvent ev) { // EXITED GESTITO etic.setText(msg+"USCITO"); } public void mouseClicked(MouseEvent ev) {} // VUOTO public void mousePressed(MouseEvent ev) {} // VUOTO public void mouseReleased(MouseEvent ev) {} // VUOTO /* ======================================================================= */ public static void main(String args[]) { cap08_es_06UNO Mio_prg=new cap08_es_06UNO(); } } Esecuzione: L’esecuzione produce la Finestra di figura: la prima mostra come si presenta all’utente all’avvio, la seconda e la terza come muta il messaggio stampato a seconda della posizione del mouse. Tale frame e identica per i due esempi 6_UNO e 6_DUE. appunti java pag. 18 esempio 6_DUE: "realizzare una finestra che segnali l'ingresso o l'uscita del mouse da essa e stampi un messaggio opportuno: <il mouse è ENTRATO> o <USCITO>". Richiesta: utilizzare la classe ADATTATORE WindowAdapter per la chiusura frame e MouseAdapter per gli eventi mouse (con la metodologia dell'esempio 5_TRE). Codifica: import javax.swing.*; import java.awt.event.*; import java.awt.*; class cap08_es_06DUE extends JFrame { String msg="Il mouse è "; JLabel etic=new JLabel(msg+" nella posizione INIZIALE"); public cap08_es_06DUE() { super("es_6_DUE"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setBounds(100,100,250,150); Container cpane=getContentPane(); cpane.setLayout(null); etic.setBounds(30,20,250,20); cpane.add(etic); setResizable(false); setVisible(true); } public void gestisci_eventi() { WindowAdapter wa=new ascoltaWindow(); // a) ADATTATORE eventi Win addWindowListener(wa); MouseListener md=new ascoltaMouse(); // b) ADATTATORE eventi Mouse addMouseListener(md); } /* ==================== la classe ADATTATORE ascoltaWindow ============== */ public class ascoltaWindow extends WindowAdapter { public void windowClosing(WindowEvent ev) { System.exit(0);} // UNICO evento definito e gestito } /* ====================================================================== */ appunti java pag. 19 /* =================== la classe ADATTATORE ascoltaMouse =============== */ public class ascoltaMouse extends MouseAdapter { public void mouseEntered(MouseEvent e) { etic.setText(msg+"ENTRATO"); // EVENTO semantico Entered. } public void mouseExited(MouseEvent e) { etic.setText(msg+"USCITO"); // EVENTO semantico Exited. } } /* ===================================================================== */ public static void main(String args[]) { cap08_es_06DUE Mio_prg=new cap08_es_06DUE(); } } Eventi di basso livello FocusListener esempio 7: "realizzare una finestra (programma) con due campi JTextField che accettino come input due interi ed eseguano la somma stampandola in una JLabel di output sulla finestra stessa.” Richiesta: La somma deve essere eseguita quando il "cursore" esce dal secondo campo (evento focusLost). Codifica: import javax.swing.*; import java.awt.event.*; import java.awt.*; class cap08_es_07 extends JFrame { JTextField testo_1=new JTextField(); JTextField testo_2=new JTextField(); JLabel etic_1=new JLabel("input:"); String msg= "PRODOTTO="; JLabel etic_2=new JLabel(msg); public cap08_es_07() { super("es_7"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setBounds(100,100,280,200); Container cpane=getContentPane(); cpane.setLayout(null); etic_1.setBounds(30,20,60,20); etic_2.setBounds(30,60,230,20); testo_1.setBounds(80,20,80,20); testo_2.setBounds(170,20,80,20); cpane.add(etic_1); cpane.add(etic_2); cpane.add(testo_1); cpane.add(testo_2); setResizable(false); setVisible(true); } public void gestisci_eventi() { WindowAdapter wa=new ascoltaWindow(); this.addWindowListener(wa); pag. 20 appunti java FocusAdapter fa=new ascoltaFuoco(); testo_2.addFocusListener(fa); // (0) // (0) } /* ================ Ascolto del solo evento WindowClosig ================ */ public class ascoltaWindow extends WindowAdapter { public void windowClosing(WindowEvent ev) {System.exit(0);} } /* ====================================================================== */ /* ============= Ascolto del solo evento focusLost =================== */ public class ascoltaFuoco extends FocusAdapter { public void focusLost(FocusEvent e) { testo_1.setRequestFocusEnabled(true); // (1) String t1=testo_1.getText(); // (2) String t2=testo_2.getText(); // (3) try { int n1=Integer.parseInt(t1); // (4) int n2=Integer.parseInt(t2); // (5) etic_2.setText(msg+" "+n1*n2); // (6) } catch (NumberFormatException ex) { // (7) etic_2.setText(msg+" Immetti NUMERI !!"); // (8) } } } /* ================================================================== */ public static void main(String args[]) { cap08_es_07 Mio_prg=new cap08_es_07(); } } Commento al Codice: Le righe di note (0) mostrano che l’ascoltatore di “focus”, che rileva l’uso del tabulatore o del mouse per fare uscire il cursore da un textfield, è stato registrato solo sul secondo campo <testo_2>; l’evento focus sarà notificato solo quando il cursore esce da questo campo. Le righe di note (1)…(8) sono il vero e proprio programma che sarà eseguito quando si rileva un FocusLost(). La nota (1) evidenzia il metodo che sposta il focus sul campo testo_1 appena questo viene tolto a testo_2. Fa passare il focus obbligatoriamente dal campo 1 al campo 2; le note (2) e (3) mostrano come si acquisisce il contenuto dei due campi. Nel blocco try..catch, note (4..8), sono gestite le possibili eccezioni dovute alla corretta trasformazione delle stringhe in numero. Attenzione: quando si debbono gestire molti programmi corrispondenti a molti eventi diversi sarebbe opportuno spostare il relativo codice in una “function separata per una migliore leggibilità del programma. Si potrebbe scrivere il metodo in questo modo: public class ascoltaFuoco extends FocusAdapter { public void focusLost(FocusEvent e) { fai_prodotto(); } } e codificare la function fai_prodotto() nel modo seguente: private static void fai_prodotto() { testo_1.setRequestFocusEnabled(true); String t1=testo_1.getText(); // (1) // (2) pag. 21 appunti java String t2=testo_2.getText(); // (3) try { int n1=Integer.parseInt(t1); // (4) int n2=Integer.parseInt(t2); // (5) etic_2.setText(msg+" "+n1*n2); // (6) } catch (NumberFormatException ex) { // (7) etic_2.setText(msg+" Immetti NUMERI!!"); // (8) } } Esecuzione: Le tre Frame di figura mostrano: la uno come si presenta il programma all’avvio, la due cosa stampa se si eseguono due tabulazioni senza immettere dati e la tre se si tabula immettendo i dati correttamente. Eventi di basso livello KeyListener esempio 8: "realizzare una finestra (programma) con due campi JtextField che accettino come input due interi ed eseguano la somma stampandola in un Jlabel di output sulla finestra stessa.” Richiesta: La somma deve essere eseguita quando si preme ENTER nel secondo campo (evento keyPressed). " Codifica: import javax.swing.*; import java.awt.event.*; import java.awt.*; class cap08_es_08 extends JFrame { JTextField testo_1=new JTextField(); JTextField testo_2=new JTextField(); JLabel etic_1=new JLabel("input:"); String msg= "PRODOTTO="; JLabel etic_2=new JLabel(msg); public cap08_es_08() { super("es_8"); disegna_frame(); gestisci_eventi(); appunti java pag. 22 } public void disegna_frame() { setBounds(100,100,280,200); Container cpane=getContentPane(); cpane.setLayout(null); etic_1.setBounds(30,20,60,20); etic_2.setBounds(30,60,230,20); testo_1.setBounds(80,20,80,20); testo_2.setBounds(170,20,80,20); cpane.add(etic_1); cpane.add(etic_2); cpane.add(testo_1); cpane.add(testo_2); setResizable(false); setVisible(true); } public void gestisci_eventi() { WindowAdapter wa=new ascoltaWindow(); this.addWindowListener(wa); KeyAdapter ka=new ascoltaKey(); testo_1.addKeyListener(ka); testo_2.addKeyListener(ka); } /* ====================================================================== */ public class ascoltaWindow extends WindowAdapter { public void windowClosing(WindowEvent ev) {System.exit(0);} } /* ====================================================================== */ /* =============== Ascolto del solo evento keyPressed =================== */ public class ascoltaKey extends KeyAdapter { public void keyPressed(KeyEvent e) { if (e.getKeyCode()==KeyEvent.VK_ENTER) { // (1) if (testo_1.hasFocus()) // (2) testo_2.requestFocus(); // (3) else if (testo_2.hasFocus()) { // (4) testo_1.requestFocus(); String t1=testo_1.getText(); String t2=testo_2.getText(); try { int n1=Integer.parseInt(t1); int n2=Integer.parseInt(t2); etic_2.setText(msg+" "+n1*n2); } catch (NumberFormatException ex) { etic_2.setText(msg+" Immetti NUMERI !!"); } } } // fine gestione ENTER } // fine Keypressed } // fine class /* ====================================================================== */ public static void main(String args[]) { cap08_es_08 Mio_prg=new cap08_es_08(); } }Commento al codice: Le uniche istruzione nuove rispetto all’esempio precedente sono le (1…4). La nota (1) mostra che tutto il programma è condizionato al fatto che il tasto premuto sia un Enter: if (e.getKeyCode()==KeyEvent.VK_ENTER). pag. 23 appunti java La nota (2) mostra la condizione di presenza del focus sul campo UNO, if(testo_1.hasFocus()), affinchè sia eseguita l’istruzione (3), che consiste nel semplice spostamento del focus sul campo DUE. La nota (4) mostra la condizione di presenza del focus sul campo DUE, if (testo_2.hasFocus()), per l’esecuzione dei calcoli. Esecuzione: Visivamente la Frame non cambia rispetto al precedente esempio Sette, cambia solo il comportamento nel senso che non è più sensibile al tasto di tabulazione ma solo a quello di Invio. Eventi Semantici ActionListener esempio 10: "realizzare una finestra (programma) con due campi JtextField che accettino come input due interi, due distinti pulsanti (Jbutton) che consentano di eseguire rispettivamente la Somma e il Prodotto stampandole in un Jlabel di output sulla finestra stessa. (evento ActionEvent). " Codifica: import javax.swing.*; import java.awt.event.*; import java.awt.*; class cap08_es_10 extends JFrame { JTextField testo_1=new JTextField(); JTextField testo_2=new JTextField(); JLabel etic_1=new JLabel("input: "); String msg= "output: "; JLabel etic_2=new JLabel(msg); JButton but_1=new JButton("SUM"); Icon ico=new ImageIcon("grillo.gif"); JButton but_2=new JButton("MLT", ico); public cap08_es_10() { super("es_10"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { setBounds(100,100,350,200); Container cpane=getContentPane(); cpane.setLayout(null); etic_1.setBounds(30,20,60,20); etic_2.setBounds(30,140,230,20); testo_1.setBounds(80,20,120,20); testo_2.setBounds(210,20,120,20); but_1.setBounds(80,60,120,80); but_2.setBounds(210,60,120,80); cpane.add(etic_1); cpane.add(etic_2); cpane.add(testo_1); cpane.add(testo_2); cpane.add(but_1); cpane.add(but_2); setResizable(false); setVisible(true); } public void gestisci_eventi() { WindowAdapter wa=new ascoltaWindow(); this.addWindowListener(wa); ascoltaButton ba=new ascoltaButton(); // (0) pag. 24 appunti java but_1.addActionListener(ba); but_2.addActionListener(ba); // (1) // (2) } /* ==================================================================== */ public class ascoltaWindow extends WindowAdapter { public void windowClosing(WindowEvent ev) {System.exit(0);} } /* ==================================================================== */ /* =========== Ascolto di actionEvent per due Pulsanti Distinti ======== */ public class ascoltaButton implements ActionListener { // (3) public void actionPerformed(ActionEvent e) { String se=e.getActionCommand(); // (4) String t1=testo_1.getText(); String t2=testo_2.getText(); try { int n1=Integer.parseInt(t1); int n2=Integer.parseInt(t2); if (se.equals("SUM")) // (5) etic_2.setText(msg+" Somma= "+(n1+n2)); else if (se.equals("MLT")) // (6) etic_2.setText(msg+" Prodotto="+n1*n2); } catch (NumberFormatException ex) { etic_2.setText(msg+" Immetti NUMERI !!"); } } // fine action } // fine class /* ====================================================================== */ public static void main(String args[]) { cap08_es_10 Mio_prg=new cap08_es_10(); } } Commento al codice: Le note (1..3) mostrano che nello stesso ascoltatore sono registrati due pulsanti but_1 e but_2. Potrebbero essere anche n. La gestione degli ActionEvent avviene nell’unico metodo public void actionPerformed(ActionEvent e); La nota (4) evidenzia che per distinguere quale pulsante è stato premuto bisogna analizzare ActionEvent con il metodo e.getActionCommand(); che restituisce l’etichetta del pulsante premuto. Le note (5) e (6) mostrano che a seconda del pulsante premuto SUM o MLT si eseguiranno le due diverse operazioni. Esecuzione: Visivamente la Frame si presenta come nelle immagini seguenti. pag. 25 appunti java Eventi Semantici ActionListener sui pulsanti di una toolBar esempio 11: "realizzare una finestra (programma) dotandolo di una JToolBar con tre pulsanti icona (Jbutton) che consentano di eseguire rispettivamente tre azioni intuitive distinte. (eventi ActionEvent). " Codifica: import javax.swing.*; import java.awt.event.*; import java.awt.*; class cap08_es_11 extends JFrame { String fileIco[]={"new.gif", "save.gif", "open.gif"}; String etic[]={"Nuovo","Salva","Apri"}; ImageIcon icona[]=new ImageIcon[3]; JButton but[]=new JButton[3]; JToolBar barra=new JToolBar(); String msg="Evento="; JLabel lb=new JLabel(msg); // // // // // public cap08_es_11() { super("es_11"); disegna_frame(); gestisci_eventi(); } public void disegna_frame() { Container cpane=getContentPane(); cpane.setLayout(new BorderLayout()); for (int i=0; i<3; i++) { icona[i]=new ImageIcon(fileIco[i]); but[i]=new JButton(icona[i]); but[i].setToolTipText(etic[i]); barra.add(but[i]); } cpane.add("North",barra); cpane.add("South",lb); setBounds(100,100,400,300); setVisible(true); } public void gestisci_eventi() { WindowAdapter wa=new ascoltaWindow(); // // // // // // (5) (6) (7) (8) (9) (10) // (11) // (12) (0) (1) (2) (3) (4) pag. 26 appunti java this.addWindowListener(wa); ascoltaButton ba=new ascoltaButton(); for (int i=0; i<3; i++) { but[i].setActionCommand(etic[i]); but[i].addActionListener(ba); } // (13) // (14) // (15) } /* ================================================================ */ public class ascoltaWindow extends WindowAdapter { public void windowClosing(WindowEvent ev) {System.exit(0);} } /* ================================================================ */ /* ==================== Gestione actionEvent ====================== */ public class ascoltaButton implements ActionListener { public void actionPerformed(ActionEvent e) { String se=e.getActionCommand(); // (16) lb.setText(msg+" "+se); // (17) } // fine action } // fine class /* ================================================================ */ public static void main(String args[]) { cap08_es_11 Mio_prg=new cap08_es_11(); } } Commento al Codice: Le note (0 … 5) mostrano come si costruisce una JtollBar con molte icone. La (0) mostra che ogni icona è caricata da un file e quindi è necessario assegnare i nomi in un array di Stringhe; La (1) mostra che ogni icona ha una etichetta con un nome simbolico che ha due funzioni: viene mostrato quando il mouse si sofferma sull’icona e viene usato per discriminare il nome dell’evento ActionEvent attivato dal click. La (2) e (3) mostrano che è necessario costruire due array, uno per contenere le “immagini grafiche caricate” ImageIcon[] e il secondo per manipolare gli oggetti Button corrispondenti but[]. La (4) invoca il costruttore di una JtoolBar. La (5) mostra che non esiste solo il Layout(null) utilizzato fino a questo momento. Ne esistono molti che noi non tratteremo, ma in questo caso è necessario utilizzare una distribuzione della ToolBar senza fare uso delle coordinate schermo come fino ad ora si è fatto per i vari componenti GUI. Il BorderLayout consente di collocare gli oggetti a North, East, South, West e Center senza dichiarare le coordinate. Il ciclo (6…10) assembla tutti i componenti della ToolBar: crea le singole icone, le pone sui pulsanti, attiva la modalità SetToolTip() che mostra l’etichetta quanto il cursore la sfiora e infine pone i singoli pulsanti sulla ToolBar con barra.add(). (11) e (12) indicano che le ToolBar sarà collocata a North mentre la Label di output a South nella Jframe. Il ciclo (13…15) mostra che ogni azione associata ad un’icona deve contenere uno specifico comando etic[] corrispondente Al suo nome simbolico e che ad ogni pulsante deve essere associato l’ascoltatore di ActionEvent. (16…17) corrispondono alla cattura e discriminazione degli eventi e alla loro stampa a fondo schermo. Per gestire diversi programmi si dovrebbero inserire al appunti java pag. 27 posto della nota (17) una serie di selezioni che attivino ciascuna un diversa routine corrispondente all’icona che ha catturato l’evento. Come ad esempio: if (se.equals(“Apri”)) esegui_apri(); else if (se.equals(“Nuovo”)) esegui_nuovo(); else if (se.equals(“Salva”)) esegui_salva(): Esecuzione: Le tre Frame di figura mostrano: la uno come si presenta il programma all’avvio, la due cosa stampa se si clicca su “Salva” e infine mostra che la JToolBar può essere spostata sulla frame nella posizione desiderata. 8.E – Esercizi [Costruzione di GUI senza eventi] 8.1 Si esplorino i packages awt e swing. “per realizzare un programma costituito da una finestra grafica Jframe non ridimensionabile 300x200, inserendo nella parte alta tre campi (JtextField) in sequenza di dimensione 80x20 che contengano ciascuno il testo predefinito <campo uno>, <campo due> e <campo tre>.” Indicazioni: Il codice da cui desumere indicazioni è quello degli esempi 2 e 3 successivamente si tratta di esplorare la documentazione on line di Java ricercando tra i metodi di Jframe le istruzioni di dimensionamento, ridimensionamento e di JtextField per la creazione dei tre campi. 8.2 Si esplorino i packages awt e swing. “per realizzare un programma costituito da una finestra grafica Jframe non ridimensionabile 200x200 con colore di sfondo nero (Color.black), inserendo nel suo centro un’icona, scelta da un file <gif> qualsiasi, inserita in una Jlabel .” Indicazioni: Il codice da cui desumere indicazioni è quello degli esempi 2 e 4 successivamente si tratta di esplorare la documentazione on line di Java ricercando tra i metodi di pag. 28 appunti java Jframe (e antenati) le istruzioni di dimensionamento, ridimensionamento e colorazione del Bkground e di Jlabel per la creazione di una label con icona. 8.3 Si esplorino i packages awt e swing. “per realizzare un programma costituito da una finestra grafica Jframe non ridimensionabile 300x200, inserendo nella parte alta un’etichetta (Jlabel) con il testo <Input:>, due campi (JtextField) in sequenza di dimensione 80x20 che contengano ciascuno il testo predefinito <UNO>, <DUE> e nella parte bassa un’altra etichetta con la scritta <Output:>.” Indicazioni: Il codice da cui desumere indicazioni è quello degli esempi 2,3 e 4, successivamente si tratta di esplorare la documentazione on line di Java ricercando tra i metodi di Jframe , JtextField e JLabel. 8.4 Si esplorino i packages awt e swing. “per realizzare un programma costituito da una finestra grafica Jframe non ridimensionabile 300x200, inserendo nella parte alta un’etichetta (Jlabel) con il testo <Input:>, due campi (JtextField) in sequenza di dimensione 80x20 che contengano ciascuno il testo predefinito <UNO>, <DUE> e nella parte bassa un’altra etichetta con la scritta <Output:>. Nella parte centrale inserisca due pulsanti (Jbutton) con la scritta <esegui>, <pulisci>.” Indicazioni: Il codice da cui desumere indicazioni è quello degli esempi 2,3 e 4, successivamente si tratta di esplorare la documentazione on line di Java ricercando tra i metodi di Jframe , JtextField, Jlabel, JButton. 8.5 “Si desidera realizzare un programma costituito da una frame ridimensionabile dall’utente che contenga gli stessi componenti dell’esercizio 8.4 ma che consenta di conservare nell’ordine sequenziale l’etichetta di input i due campi i due pulsanti e infine l’etichetta output.” Richieste: Non utilizzare il setLayout(null) come nei precedenti esercizi la setLayout(new flowLayout()); aggiungendo, uno dopo l’altro, tutti i componenti al pannello. Provarne il comportamento ridimensionando la frame. [Costruzione di GUI con eventi] 8.6 “realizzare un programma costituito da una finestra il cui sfondo cambi colore all’entrata e all’uscita del mouse”. Indicazioni: Utilizzando l’ascoltatore MouseListener come nell’esempio 6_DUE del capitolo modificare opportunamente i due metodi di gestione degli eventi assegnando nei due casi i colori rosso (Color.red) e verde (Color.green). 8.7 “realizzare un programma costituito da una finestra che consenta di immettere un numero intero compreso tra 1 e 10 e stampi in campo di output un array di n componenti intere comprese tra (-100 e 100) generate in modo random”. Richieste: Utilizzare l’ascoltatore KeyListener come nell’esempio 8 del capitolo in modo che alla pressione del tasto ENTER nel campo esegua quanto richiesto. Inserire le etichette di commento per l’input e l’output e in controllo dell’input. La struttura del programma e la gerarchia dei metodi deve essere quella adottata nel capitolo come dal grafo ad albero: disegna_frame() main() e_8_07() windowClosing() gestisci_Eventi() keyPressed() pag. 29 appunti java 8.8 “Realizzare un programma costituito da una finestra che consenta di immettere due numero naturali e stampi in campo di output sia il massimo comun divisore che il minimo comune multiplo”. Richieste: Utilizzare l’ascoltatore KeyListener come nell’esempio 8 del capitolo in modo che alla pressione del tasto ENTER nel secondo campo esegua quanto richiesto. Inserire le etichette di commento per l’input e l’output e il controllo dell’input. Rispettare la scomposizione standard in metodi, separando come dal grafo il codice dei due metodi MCD() ed mcm(): disegna_frame() main() e_8_08() windowClosing() gestisci_Eventi() MCD() keyPressed() mcm() main() chiama il costruttore di e_8_08() il quale nell’ordine solito invoca disegna_frame() e gestisci_eventi(); gestisci_eventi() attiva come nell’esempio 8 il metodo KeyPressed() che al suo interno richiamerà i due metodi statici MCD() e mcm() con gli opportuni parametri e stamperà i valori restituiti. 8.9 “Realizzare un programma come quello dell’esercizio 8.7 con l’aggiunta di un pulsante e di un secondo campo di output per permettere, che alla pressione del pulsante, venga stampato nel nuovo campo di output l’array ordinato.” Richieste:Utilizzare KeiListener per gestire l’evento che attiva il metodo crea_mostra() che genera l’array e ActionListener per gestire la pressione del pulsante che attiva il metodo ordina_stampa() secondo il grafo seguente: disegna_frame() windowClosing() gestisci_Eventi() keyPressed() crea_mostra() actionPerformed() ordina_stampa() e_8_09() 8.10 “Realizzare un programma come quello dell’esercizio 8.7 con l’aggiunta di un pulsante e ma l’uso di un solo campo di output (JtextArea) per permettere, che alla pressione del pulsante, venga stampato nel campo di output sia l’array disordinato che quello ordinato separata da un commento opportuno.” Richieste: Rispettare la scomposizione standard realizzando la seguente finestra di figura.