5.0 - swing

38
Ing. Aime – Programmazione grafica in Java con la libreria Swing 1 PROGRAMMAZIONE GRAFICA Creazione di interfaccie utente “grafiche”, ovvero basate su concetti quali finestra, casella di testo, bottone, barra degli strumenti, menu. Elementi fondamentali: Componenti e composizione: l’interfaccia grafica viene costruita assemblando componenti pronti, quali finestre, bottoni, caselle di testo; Layout: posizionamento degli elementi nell’interfaccia grafica. E’ un problema non banale quando si vuole che l’applicazione sia multipiattaforma e indipendente dalla risoluzione e dalla dimensione dei caratteri. Event-oriented programming: il programma non è più in comando dell’interazione con l’utente. Deve reagire appropriatamente alle azioni svolte dall’utente. Programmazione grafica: è possibile creare componenti che si disegnano autonomamente. Librerie per la grafica in Java: AWT: presente nel JDK, risale a Java 1.0. E’ poco flessibile, possiede meno componenti. Ogni componente è nativo, ovvero ha lo stesso aspetto degli altri componenti del sistema operativa; Swing: presente nel JDK, risale a Java 2. Flessibile, potente, anche se più complessa da usare. Indipendente dalla piattaforma e skinnable (vedi Look And Feel).

Upload: matteo-martorella

Post on 29-Jun-2015

77 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 1

PROGRAMMAZIONE GRAFICA Creazione di interfaccie utente “grafiche”, ovvero basate su concetti quali finestra, casella di testo, bottone, barra degli strumenti, menu. Elementi fondamentali:

• Componenti e composizione: l’interfaccia grafica viene costruita assemblando componenti pronti, quali finestre, bottoni, caselle di testo;

• Layout: posizionamento degli elementi nell’interfaccia

grafica. E’ un problema non banale quando si vuole che l’applicazione sia multipiattaforma e indipendente dalla risoluzione e dalla dimensione dei caratteri.

• Event-oriented programming: il programma non è più in

comando dell’interazione con l’utente. Deve reagire appropriatamente alle azioni svolte dall’utente.

• Programmazione grafica: è possibile creare componenti

che si disegnano autonomamente. Librerie per la grafica in Java:

• AWT : presente nel JDK, risale a Java 1.0. E’ poco flessibile, possiede meno componenti. Ogni componente è nativo, ovvero ha lo stesso aspetto degli altri componenti del sistema operativa;

• Swing: presente nel JDK, risale a Java 2. Flessibile, potente, anche se più complessa da usare. Indipendente dalla piattaforma e skinnable (vedi Look And Feel).

Page 2: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 2

COMPOSIZIONE

Osservazioni:

• Componenti: la finestra mostra vari componenti, quali etichette (nome, descrizione), caselle di testo, bottoni, liste a discesa, radio e check buttons, liste, e pannelli, ovvero generici contenitori di altri componenti (decorati con un bordo e un titolo)

• Composizione: la finestra contiene un pannello, che contiene dei componenti, ma anche un secondo pannello, il quale contiene a sua volta dei bottoni;

Finestra

Pannello (contenitore)

Secondo pannello

Componenti

Page 3: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 3

POSIZIONAMENTO E GESTIONE LAYOUT

Ogni componente è dotato di un sistema di riferimento cartesiano, la cui unità di misura è il pixel (la cui dimensione dipende dal numero di pixel presenti sullo schermo e dalla dimensione dello schermo, per una definizione più accurata si veda http://it.wikipedia.org/wiki/Pixel). Ad esempio, possiamo dire che l’etichetta nome ha una posizione (3, 6) rispetto all’origine, e una dimensione di 20 per 8 pixel. Ciascun contenitore ha il proprio riferimento cartesiano. La posizione di jButton2, ad esempio, è riferita al sistema cartesiano di Pannello2, non all’intera finestra.

X

Y

Page 4: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 4

Il dimensionamento e il posizionamento fisso in pixel non sono però affidabili: se si cambia la dimensione o il tipo dei font o la risoluzione del video, o si cerca di ridimensionare la finestra, si possono ottenere componeti sovrapposti, mal distribuiti, o posizionati fuori dall’area visibile. Java introduce i layout manager, gestori del posizionamento, che risolvono questi problemi ricalcolando la posizione assoluta dei componenti in funzione delle suddette variabili.

X

Y

X

Y

Page 5: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 5

EVENT ORIENTED PROGRAMMING Paradigma di interazione in un programma testuale: il software propone delle domande all’utente, e si aspetta una risposta (testuale). Il programma di norma interrompe la sua esecuzione nell’attesa della risposta, la riposta è una sola, è sufficiente verificare che sia appropriata. � Il programma domina l’interazione con l’utente. Il programma termina quanto termina la main. Paradigma di interazione in un programma grafico: il programma predispone una interfaccia utente grafica, l’utente decidere cosa quale azioni vuole eseguire. Ad esempio, può compilare prima il campo nome e poi la descrizione, e premere ok senza aver fornito la sua età. Il programma di norma non termina quanto termina la main, ma quando viene chiusa l’ultima finestra. L’utente domina l’interazione, il programma può soltanto “reagire” agli stimoli forniti dall’utente. Quindi, il programma resta in attesa di “eventi” generati dall’azione dell’utente, ed esegue determinate routine quando accadono eventi ritenuti interessanti. Vi sono molti eventi, ma il programma ne ascolterà soltanto una parte. Ad esempio, relativamente ad un bottone siamo interessati al click sul bottone, ma probabilmente non al fatto che qualcuno ha premuto il tasto “A” mentre il bottone era attivo (anche se potremmo ascolatare anche questo evento). Alla stessa maniera, non saremo direttamente interessati ad eventi quali il ridimensionamento di una finestra (ma il layout manager, al contrario, sarà molto interessato in questi ultimi).

Page 6: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 6

L’utente opera sulla finestra del programma con mouse e tastiera. La virtual machine e la libreria Swing ricevono questi eventi “grezzi”, o di basso livello, e li inviano al componente a cui sono dedicati. Per decidere quale componente è il destinatario, vengono usati due algoritmi:

• se l’evento origina dal mouse, si determina quale è il componente che sta sotto il puntatore del mouse;

• se l’evento origina dalla tastiera, si invia al componente che ha il “focus” (di norma tale componente è evidenziato con un bordo particolare). Il “focus” può essere spostato ciccando sui componenti o premendo i tasti TAB e MAISC-TAB.

Il componente notifica questi eventi così come li ha ricevuti, ma crea anche eventi di più alto livello. Ad esempio, un click può comportare la selezione/deselezione: verrà notificato sia l’evento di click, che un evento di selezione/deselezione. Un programma grafico aggancia degli “ascoltatori” ai componenti, per poter ascoltare i particolari eventi a cui è interessato e reagire di conseguenza.

Virtual Machine + Swing

Componente

Mouse

Tastiera

Mouse

Tastiera

Mouse

Tastiera

Semantici

Ascoltatori

Page 7: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 7

Come sempre in Java, questi concetti sono mappati su classi:

• un evento è rappresentato da un oggetto, istanza di una particolare classe di evento, riporta un riferimento al componente che lo ha generato e ulteriori informazioni specifiche in funzione del tipo di evento (ad esempio, un evento di click riporta quale bottone del mouse è stato premuto, se erano premuti alcuni tasti speciali sulla tastiera insieme al click, eccetera);

• un ascoltatore (listener) è un oggetto che implementa una determinata interfaccia. Quando un evento viene scatenato, verrà invocato uno dei metodi di questa interfaccia. Ad esempio, MouseListener è una interfaccia, fra i vari metodi di questa interfaccia abbiamo public void mouseClicked(MouseEvent e); Quando l’evento di click viene scatenato, verrà invocato questo metodo passando come parametro il MouseEvent.

• l’ascoltatore di deve registrare presso il componente per poter ascoltare (e può rimoeve la registrazione per smettere di ascoltare). public void addMouseListener(MouseListener l) public void removeMouseListener(MouseListener l)

• Un componente può avere più ascoltatori, il medesimo ascoltatore può ascoltare eventi da più componenti.

Ascoltatore1

Ascoltatore2

Bottone 1

Bottone 2

E1

E2

E1

Page 8: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 8

RIASSUMENDO Una interfaccia grafica viene costruita mediante i seguenti passi:

1. si creano e si configurano i componenti; 2. si assembla l’interfaccia inserendo componenti base dentro i

contenitori (pannelli) e questi dentro una finestra; 3. si specifica la gestione del layout (algoritmo generale,

dettagli per i singoli componenti) 4. si agganciano dei listener ai componenti per poter reagire alle

azioni dell’utente. A run time, il programma aspetta gli input dell’utente e reagisce. Alcune interazioni sono già predisposte nei componenti (ad esempio, un campo di testo reagire alla tastiera inserendo i caratteri premuti nella casella). Altre interazioni sono programmate nei listener, e vengono attivate quando l’utente esegue determinate azioni (ad esempio, premere un bottone).

ESEMPIO

Page 9: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 9

import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.Date; class FirstExample extends JPanel implements ActionListener { JButton bottone; JTextField testo; public FirstExample() { // costruzione e configurazione componenti bottone = new JButton("Premi qui"); testo = new JTextField(); testo.setColumns(20); // aggiunta dei componenti al pannello this.add(bottone); this.add(testo); // aggancio i listener (me stesso) bottone.addActionListener(this); } // dichiarato in ActionListener // verrà invocato quando il bottone sarà premut o public void actionPerformed( ActionEvent event) { Date ora = new Date(); testo.setText(ora.toString()); System.out.println("Sono stato invocato da: \n" + event.getSource()); System.out.println(); } public static void main(String[] args) { JFrame frame = new JFrame("Primo esempio"); frame.setContentPane(new FirstExample()); frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); // la main termina, ma il programma no!!! } }

Page 10: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 10

GERARCHIA DEI COMPONENTI IN JAVA

Osservazioni: • ogni componente grafico è rappresentato da una classe. • i componenti sono disposti lungo una gerarchia di

ereditarietà � i metodi presenti nelle classi base sono disponibili in tutte le sottoclassi!

• Nell’ovale sono riportate le classi che rappresentano le finestre. Di due tipi, normale (JFrame), di dialogo (usata di norma per chiedere all’utente informazioni).

Object

Component

Container

Window

Frame Dialog

JFrame JDialog

JComponent

JPanel

JTextComponent

JTextField

JTextArea

JList

AbstractButton

JToggleButton

JCheckBox JRadioButton

JButton

AWT

Swing

Page 11: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 11

• In corsivo le classi di AWT, le classi di Swing iniziano tutte per J.

GERARCHIA DEGLI EVENTI

Ogni evento viene accompagnato da un oggetto che lo rappresenta. Per ogni evento, è possibile risalire al componente che lo ha generato invocando il metodo public Object getSource();

Object

EventObject

AWTEvent

ActionEvent ItemEvent ComponentEvent

ContainerEvent InOutEvent WindowEvent

KeyEvent MouseEvent Package java.awt.event

Page 12: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 12

COMPONENTI AWT Component Classe base (astratta) di tutti i componenti grafici. Di seguito sono riportati alcune proprietà e eventi del componente. Alcune proprietà (manipolate con metodi set/get) Background Color di sfondo Bounds Area occupata dal componente nel suo

contenitore (Rectangle) Enabled Un componente riceve gli eventi solo se abilitato Font Tipo di carattere usato nel componente Focusable Se il componente può ricevere il focus Foreground Colore di primo piano Location Posizione dell’angolo in alto a sinistra (Point) MinimumSize Dimensione minima per il componente

(Dimension) MaximumSize Dimensione massima per il componente Parent Il contenitore in cui è collocato il componente.

Può essere null Size Dimensione del componente (classe Dimension) Visibile Se vero, il componente è visibile. Usato anche per

mostrare le finestre a video dopo averle costruite

Alcuni fra i listener accettati KeyListener Per ascoltare eventi come la pressione di

tasti (solo se il componente ha il focus) MouseListener Eventi base del mouse (click, ingresso e

uscita del puntatore) MouseMotionListener Eventi avanzati, movimento,

trascinamento MouseWheelListener Eventi della rotellina del mouse, se

presente

Page 13: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 13

Esiste poi un metodo che viene invocato ogni volta che il componente deve essere disegnato: public void paint(Graphics g); dove Graphics è un oggetto dotato di metodi per disegnare linee, rettangoli, ellissi, poligoni, eccetera. Ogni componente ridefinisce questo metodo per poter disegnare correttamente il suo aspetto. Container E’ un contenitore di altri componenti. Pertanto:

• esistatono metodi per aggiungere/rimuovere i componenti contenuti, e per ispezionare quali componenti sono presenti;

• è possibile associare un layout manager public Component add(Component comp); public add(Component comp, Object constraints); public void remove(Component comp); public int getComponentCount(); public Component getComponent(int n); public void setLayout(LayoutManager mgr);

Page 14: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 14

COMPONENTI SWING JFrame La finestra. Alcune proprietà (manipolate con metodi set/get) Title Titolo della finestra Resizable Se vero, la finestra è ridimensionabile DefaultCloseOperation

Operazione svolta alla chiusura. Valori possibili: WindowConstants.DO_NOTHING_ON_CLOSE WindowConstants.HIDE_ON_CLOSE WindowConstants.DISPOSE_ON_CLOSE WindowConstants.EXIT_ON_CLOSE

import javax.swing.*; import java.awt.*; public class Finestra extends JFrame { public Finestra(String title) { super(title); setSize(200, 200); setLocation(100, 200); setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { System.out.println( "Prima di creare la finestra"); Finestra f = new Finestra("Prima finestra"); f.setVisible(true); System.out.println( "Sto per uscire dalla main"); } }

Page 15: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 15

JComponent Classe base dei componenti Swing. Aggiunge molti metodi e proprietà, ma la maggior parte sono “avanzati”, e non verranno presi in considerazione. Alcune proprietà (manipolate con metodi set/get) Border Bordo del componente (sottoclassi di Border) Opaque Boolean, indica se lo sfondo è trasparente o pieno

(default, trasparente) Metodi per il disegno (invocato dalla paint di JComponent, si occupa di richiamare paintComponent dopo aver disegnato il bordo): protected void paintComponent(Graphics g);

In aggiunta, tutti i discendenti di JComponent sono in grado di modificare il proprio aspetto quando viene cambiato il “Look and Feel”.

JPanel Pensato per essere un semplice contenitore di componenti. Non ha nessuna differenza particolare, a meno che il look and feel non imponga qualche differenza estetica (ad esempio, uno sfondo grafico). JLabel Semplice etichetta di testo. Attenzione: JLabel non è passivo, ha tutta la gamma di eventi ereditati dai suoi padri, come ad esempio la gestine degli eventi del mouse, presente sin dalla radice della gerarchia, Container.

Alcune proprietà (manipolate con metodi set/get) Text Il testo mostrato nell’etichetta

Page 16: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 16

AbstractButton e i bottoni Classe base astratta di tutti i bottoni. Qualunque bottone sarà dotato di un testo, la proprietà text . Inoltre, qualunque bottone emette un ActionEvent ogni volta che il bottone viene premuto (con il mouse, o con la barra spaziatrice quando il bottone ha il focus). Un ascolatore di ActionEvent deve implementare ActionListener: public interface ActionListener extends EventListener { public void actionPerformed(ActionEvent e); }

L’ascoltatore dovrà poi registrarsi presso il bottone usando il metodo: public void addActionListener(ActionListener l);

JButton è una sottoclasse di AbstractButton semplice, non vi sono funzionalità aggiuntive degne di nota. JToggleButton è una sottoclasse di AbstractButton. Ha lo stesso aspetto di un JButton, ma può restare “premuto”. Aggiunge una proprietà selected (setSelected, isSelected) per indicare il suo stato (premuto o non premuto). JCheckBox è una sottoclasse di JToggleButton, con un aspetto grafico differente.

Page 17: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 17

JRadioButton è una ulteriore sottoclasse di JToggleButton. Ha un aspetto grafico differente, e può essere incluso in un ButtonGroup per creare un insieme di selezioni esclusive fra loro. Ad esempio: import javax.swing.*; import java.awt.*; import java.awt.event.*; public class RadioSample extends JPanel implements ActionListener { JRadioButton rbtUno, rbtDue, rbtTre; ButtonGroup group; JLabel label; public RadioSample() { // crea e configura i componenti rbtUno = new JRadioButton("Uno"); rbtUno.setSelected(true); rbtDue = new JRadioButton("Due"); rbtTre = new JRadioButton("Tre"); label = new JLabel("Seleziona un bottone"); // crea e configura il gruppo group = new ButtonGroup(); group.add(rbtUno); group.add(rbtDue); group.add(rbtTre); // aggiungi i componenti add(rbtUno); add(rbtDue); add(rbtTre); add(label); // gestione eventi rbtUno.addActionListener(this); rbtDue.addActionListener(this); rbtTre.addActionListener(this); }

Gestione di più sorgenti di evento con lo stesso listener

Page 18: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 18

public void actionPerformed(ActionEvent evt) { JRadioButton src = (JRadioButton) evt.getSource(); System.out.println("Evento da " + src.getText()); if(src.isSelected()) label.setText("Selezionato: " + src.getText()); } public static void main(String[] args) { JFrame frame = new JFrame("Radio sample"); frame.setContentPane(new RadioSample()); frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } }

JTextField e JTextArea Entrambi i componenti espongono la proprietà text che consente di leggere/impostare il testo contenuto. JTextField è pensato per testi brevi, disposti su una sola riga. JTextArea al contrario permette di scrivere testi ampi. Inoltre, è capace di effettuare il ritorno a capo automatico quando siano state attivate le proprietà wrapStyleWord e lineWrap . Poiché JTextArea può raggiungere dimensioni ragguardevoli, è opportuno aggiungere delle barre di scorrimento. Per tale scopo esiste JScrollPane, un contenitore dotato di barre di scorrimento pensato per contenere componenti troppi “ampi” per essere visualizzati per intero.

Page 19: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 19

import javax.swing.*; import java.awt.*; import java.awt.event.*; public class TextSample extends JPanel implements ActionListener { JTextField testo; JTextArea area; JScrollPane scroll; JButton btnAggiungi; public TextSample() { // crea e configura i componenti testo = new JTextField("Campo di testo"); testo.setColumns(20); btnAggiungi = new JButton("Aggiungi testo"); area = new JTextArea("TextArea"); area.setLineWrap(true); area.setWrapStyleWord(true); scroll = new JScrollPane(area); scroll.setPreferredSize( new Dimension(300, 200)); // aggiungi i componenti add(testo); add(btnAggiungi); add(scroll); // gestione eventi btnAggiungi.addActionListener(this); } public void actionPerformed(ActionEvent evt) { area.setText(area.getText() + testo.getText()); } public static void main(String[] args) { ... } }

Page 20: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 20

GESTIONE DEL LAYOUT Ogni Container è dotato di un layout manager, che calcola la posizione dei componenti in base alle loro dimensioni minime/preferite/massime e in base ad eventuali vincoli aggiuntivi specificati quando si inseriscono i componenti nel container. Vedremo tre tipi di layout:

• FlowLayout: è il layout di default dei JPanel, ovvero il layout manager visto sino ad ora;

• BorderLayout : un semplice layout manager, utile in varie occasioni

• GridBagLayout : il layout manager più flessibile, ma anche il più difficile da utilizzare, tanto complesso che faremo uso di una classe di supporto per semplificarne l’utilizzo.

I constraint di norma sono specificati quando si aggiunge il componente al Container. Vi sono infatti più metodi per l’aggiunta, in overload, fra i quali troviamo: void add(Component comp); void add(Component comp, Object constraint);

Page 21: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 21

FlowLayout Un layout manager che dispone i componenti per riga, ciascuno dimensionato secondo la sua preferred size. Se il container non è sufficientemente largo, il layout manager va a capo.

Page 22: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 22

BorderLayout Il border layout prevede la presenza di un massimo di 5 componenti, disposti come in figura:

Gli elementi sono disposti come i 4 segni cardinali, più il centro. L’elemento di centro si allarga sia in altezza che in larghezza, gli altri solo in larghezza (west e east) o solo in altezza (north e south).

Page 23: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 23

// aggiungi i componenti add(button1, BorderLayout.NORTH); add(button2, BorderLayout.CENTER); add(button3, BorderLayout.EAST); add(button4, BorderLayout.WEST); add(button5, BorderLayout.SOUTH);

Nota: non è obbligatorio riempire tutte le posizioni. GridBagLayout con GridBuilder In questa sede verrà presentato un sottoinsieme delle possibilità del GridBagLayout. L’idea di base è quella di collocare i componenti nelle celle di una griglia “elastica”, ovvero capace di ridimensionarsi quando il contenitore viene ridimensionato. Ogni riga e colonna ha un peso. Un peso nullo significa che la riga o la colonna faranno uso della dimensione minima dei componenti in esse, e non cercheranno di allargarsi, un peso non nullo al contrario consentirà alla colonna di allargarsi. Maggiore il peso, maggiore lo spazio occupato dalla riga o dalla colonna.

0 0

0

0

1

1

Page 24: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 24

Ogni componente è posizionato in una cella, ma può eventualmente occupare più celle (grid size maggiore di uno). Nella figura sono mostrati 4 componenti, tre dei quali occupano più di una cella.

0 0

0

0

1

1

0 0

0

0

1

1

Page 25: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 25

Ogni componente può sfruttare in modo diverso l’area della cella: può occupare soltanto la sua area preferenziale, estendersi in larghezza, in altezza, o in entrambe le direzioni:

Se il componente non sfrutta tutta l’area della cella, può essere posizionato in modo diverso al suo intero:

Infine, un componente può avere una spaziatura rispetto al bordo della cella, detto inset (usato per evitare che i componenti siano troppo addossati l’uno all’altro):

0 0

1

1

0 0

1

1

1

NorthWest North NorthEast

West Center East

SouthWest South SouthEast

Page 26: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 26

Per creare un layout con il GridBagLayout occorre decidere: • quante righe e quante colonne sono necessarie; • quali pesi dare a righe e colonne; • quali posizioni e numero di celle saranno occupate dai

componenti; • come i componenti si allargano e, se necessario, in che

posizione devono essere collocati. GridBuilder facilita la codifica di queste operazioni. Nel costruttore vengono specificati il container, i pesi e l’inset: // 5 righe, con i rispettivi pesi, 2 colonne, // un inset pari a 3 pixel GridBuilder gb = new GridBuilder(container, new double[] { 0, 0, 0, 1, 0 }, new double[] { 0, 1}, 3);

Il grid builder tiene traccia della riga e della colonna correnti , partendo da 0,0. Ogni volta che si aggiunge un componente la colonna viene incrementata, se si raggiunge la fine riga, si passa automaticamente alla riga successiva: non è quindi necessario specificare riga e colonna per i componenti, si continua semplicemente a chiamare la add per aggiungere nuovi componeti. gb.add(new JLabel(“Etichetta”)); gb.add(new JTextFiled(“Prova”)); gb.add(new Jlabel(“Etichetta2”));

Page 27: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 27

gb.add(new JButton(“Bottone”));

Se è necessario saltare una cella si può chiamare skip() , se è necessario andare a capo prima della fine della riga, newLine() . E’ inoltre possibile leggere e impostare row e column con gli opportuni getter e setter. Il metodo add restituisce un oggetto GridConstraints , che consente di specificare i restanti parametri, ovvero dimensione, spazio utlizzato e posizionamento. public interface GridConstraints {

public GridConstraints gridSize(int gridWidth, int gridHeight); public GridConstraints north(); public GridConstraints northEast(); public GridConstraints northWest(); public GridConstraints east(); public GridConstraints center(); public GridConstraints west(); public GridConstraints southEast(); public GridConstraints south(); public GridConstraints southWest(); public GridConstraints fillHorizontal(); public GridConstraints fillVertical(); public GridConstraints fillBoth(); }

Ogni metodo restituisce un riferimento all’oggetto GridConstraints stesso, questo consente di effettuare più chiamate in cascata: gb.add(new JLabel(“Ciao”)).

Page 28: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 28

gridSize(2, 1).fillHorizontal().north();

Attenzione: specificare una gridSize > 0 non fa spostare il cursore del grid builder. Se una cella è stata coperta da un componente con larghezza > 0 bisogna saltarla chiamando skip()

Page 29: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 29

Esempio Si costruisca una finestra come la seguente:

Per prima cosa, individuiamo righe, colonne e pesi:

0 1

0

0 0

1

0

Page 30: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 30

Questo individua anche la posizione degli elementi. Notiamo però che l’etichetta Modulo di registrazione e il bottone Ok sono centrati rispetto alla finestra � devono occupare una intera riga per essere posizionati al centro. Pensiamo all’occupazione di spazio: l’etichetta del nome sembra occupare tutto lo spazio orizzontale, la text area del commento, anche quello verticale. Infine, il posizionamento. Le etichette Nome e Età e il testo per l’età sono a West, Commento è a NorthWest i restanti sono al centro. Il codice di costruzione dentro un JPanel allora è: GridBuilder gb = new GridBuilder(this, new double[] { 0, 0, 0, 1, 0 }, new double[] { 0, 1}, 3); gb.add(new JLabel("Modulo di registrazione")).gridSize(2, 1); gb.newLine(); // attenzione! gb.add(new JLabel("Nome")).west(); gb.add(new JTextField()).fillHorizontal(); gb.add(new JLabel("Età")).west(); gb.add(new JTextField(3)).west(); gb.add(new JLabel("Commento")).northWest(); JscrollPane scroll = new JScrollPane( new JTextArea()); gb.add(scroll).fillBoth(); gb.add(new JButton("Ok")).gridSize(2, 1);

Page 31: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 31

Reazione del pannello ai ridimensionamenti:

Page 32: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 32

LAYOUT E COMPOSIZIONE DI PANNELLI Ogni pannello è dotato di un proprio layout manager. Se non si riesce ad ottenere il risultato voluto con un solo layout manager, si possono comporre fra loro i pannelli e usare un layout manager separato per ciascuno. Ad esempio:

In questa finestra sono presenti tre pannelli:

• il panello principale, con un BorderLayout, completamente ricoperto dagli altri;

• il pannello dati, posto al centro del pannello principale, dotato di un GridBagLayout

• il pannello con i bottoni, a sud del panello principale, con un flow layout allineato a destra.

dataPanel (GridBagLayout)

buttonPanel (FlowLayout, destra)

Principale (BorderLayout)

Page 33: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 33

class MultiLayout extends JPanel { JTextField txfName; JTextField txfSurname; JTextField txfAge; JButton btnOk; JButton btnCancel; public MultiLayout() { JPanel dataPanel = new JPanel(); txfName = new JTextField(); txfName.setColumns(20); txfSurname = new JTextField(); txfSurname.setColumns(20); txfAge = new JTextField(); txfAge.setColumns(3); GridBuilder builder = new GridBuilder(dataPanel, new double[] {0,0,0, 1}, new double[] {0,1}, 3); builder.add(new JLabel("Nome")).west(); builder.add(txfName).fillHorizontal(); builder.add(new JLabel("Cognome")).west(); builder.add(txfSurname).fillHorizontal(); builder.add(new JLabel("Età")).west(); builder.add(txfAge).west(); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout( new FlowLayout(FlowLayout.RIGHT)); btnOk = new JButton("Ok"); btnCancel = new JButton("Cancel"); buttonPanel.add(btnOk); buttonPanel.add(btnCancel); setLayout(new BorderLayout()); add(dataPanel, BorderLayout.CENTER); add(buttonPanel, BorderLayout.SOUTH); } }

Page 34: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 34

DISEGNO LIBERO CON SWING Ogni classe di Swing si disegna appropriatamente usando il metodo paintComponent. E’ possibile creare una propria classe che ridefinisce (override) il metodo paintComponent per disegnare liberamente con l’oggetto Graphics. I metodi per disegnare figure aperte e testo sono: drawLine(), drawRect(), drawRoundRect(), draw3DRect(), drawOval(), drawArc(), drawString(), drawPolygon(), drawPolyLine()

I metodi per disegnare figure piene sono: fillRect(), fillRoundRect(), fill3DRect(), fillOval(), fillArc(), fillPolygon(), fillPolyLine()

Infine, i seguenti metodi impostano il colore e il font (ovvero, il tipo di carattere usato): getColor(), getFont(), setColor(), setFont().

I colori vengono specificati con gli oggetti Color. Si può istanziare un oggetto Color specificando le componenti RGB o usare le costanti simboliche definite in Color, come Color.BLACK, Color.RED, Color.GREEN, … I font possono essere creati specificando il nome di un carattere (potete usare “Arial”, “Times New Roman”, “Courier”), lo stile (Font.BOLD, Font.ITALIC o metterli insieme con Font.BOLD | Font.ITALIC), e la dimensione.

Page 35: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 35

Tutti i metodi di disegno accettano delle coordinate: sono coordinate in pixel rispetto all’origine. import javax.swing.*; import java.awt.*; import java.awt.event.*; class Grafica1 extends JPanel { public void paintComponent(Graphics g) { g.setColor(Color.RED); g.fillOval(80, 10, 40, 20); g.setColor(Color.GREEN); g.fillRoundRect(80, 160, 40, 40, 10, 5); g.setColor(Color.BLUE); g.drawArc(20, 20, 160, 160, 90, 270); g.drawLine(20, 100, 100, 100); g.drawLine(100, 20, 100, 180); g.drawRect(10, 90, 20, 20); g.setColor(Color.BLACK); g.setFont(new Font("Arial", Font.BOLD, 12)); g.drawString("Testo libero!", 140, 80); } public static void main(String[] args) { ... } }

Page 36: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 36

FINESTRE DI DIALOGO Una finestra di dialogo rappresenta una finestra secondaria, usata di norma per confermare inserimenti, aggiungere dettagli, eccetera (si pensi alle finestre di dialogo formato/carattere di Word, o alla finestra Configure/Options di JCreator). Di norma queste finestre hanno un padre e sono modali. Una finestra è modale rispetto al padre quando impedisce qualunque interazione con il padre fino a che non viene chiusa. Di fatto, una volta chiamato setVisible(true) il codice del padre resta congelato. I costruttori possono avere le seguenti forme: JDialog(Frame parent, String title, boolean modal); JDialog(Dialog parent, String title, boolean modal) ;

Dato un componente comp si può ottenere il Frame che lo contiene con: Frame padre = OptionPane.getFrameForComponent(comp) ;

Al di la di questa differenza, una JDialog si comporta esattamente come un JFrame: è una finestra, ha un content pane, un metodo pack, e tutti gli altri metodi ereditati da Component.

Page 37: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 37

import javax.swing.*; import java.awt.*; import java.awt.event.*; public class DialogSample extends JPanel implements ActionListener { JCheckBox check; public DialogSample() { check = new JCheckBox("Prova la selezione"); JButton btnSeleziona = new jButton("Seleziona") ; add(btnSeleziona); add(check); btnSeleziona.addActionListener(this); } public void actionPerformed(ActionEvent event) { SelectionDialog dialog = new SelectionDialog(this); System.out.println("Il codice si blocca e “ + “ aspetta che la dialog si chiuda"); dialog.setVisible(true); System.out.println("Il codice prosegue"); if(dialog.risposta) { check.setSelected(true); check.setText("Hai risposto si"); } else { check.setSelected(false); check.setText("Hai risposto no"); } } public static void main(String[] args) { JFrame frame = new JFrame("Due finestre"); frame.setContentPane(new DialogSample()); frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } }

Page 38: 5.0 - Swing

Ing. Aime – Programmazione grafica in Java con la libreria Swing 38

class SelectionDialog extends JDialog implements ActionListener { boolean risposta = false; JButton btnSi; JButton btnNo; public SelectionDialog(Component parent) { super(JOptionPane.getFrameForComponent(parent), "Selezione", true); JPanel buttons = new JPanel(); JLabel label = new JLabel("Scegli una risposta"); btnSi = new JButton("Si"); btnNo = new JButton("No"); buttons.add(label); buttons.add(btnSi); buttons.add(btnNo); setContentPane(buttons); pack(); btnSi.addActionListener(this); btnNo.addActionListener(this); } public void actionPerformed(ActionEvent event) { risposta = event.getSource() == btnSi; // chiudi la finestra e rilascia le risorse setVisible(false); dispose(); }