Sei sulla pagina 1di 38

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).

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


COMPOSIZIONE Finestra

Componenti

Pannello Secondo
(contenitore) pannello

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;

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


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.

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


X

Y
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.

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


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).

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


Mouse Mouse Mouse

Tastiera Tastiera Tastiera

Semantici

Virtual Machine Componente Ascoltatori


+ Swing
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.

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


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.

Bottone 1 E1 Ascoltatore1

E1

Bottone 2 E2 Ascoltatore2

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


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

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


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à premuto
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!!!
}
}

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


GERARCHIA DEI COMPONENTI IN JAVA

Object

Component
AWT
Container Swing

Window JComponent

Frame Dialog JPanel JList

JFrame JDialog JTextComponent

JTextField
AbstractButton
JTextArea
JToggleButton JButton

JCheckBox JRadioButton

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).

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


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

GERARCHIA DEGLI EVENTI

Object

EventObject

AWTEvent

ActionEvent ComponentEvent ItemEvent

ContainerEvent InOutEvent WindowEvent

KeyEvent MouseEvent Package


java.awt.event

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();

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


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

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


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);

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


COMPONENTI SWING
JFrame
La finestra.

Alcune proprietà (manipolate con


metodi set/get)
Title Titolo della finestra
Resizable Se vero, la finestra è ridimensionabile
DefaultClose Operazione svolta alla chiusura. Valori possibili:
Operation 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");
}
}

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


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

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


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.

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


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 Gestione di più


rbtUno.addActionListener(this); sorgenti di
rbtDue.addActionListener(this); evento con lo
rbtTre.addActionListener(this); stesso listener
}

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


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.

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


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) {


...
}

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


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);

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


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.

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


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).

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


// 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 0 1 0
uso della dimensione
minima dei componenti in 0
esse, e non cercheranno di
allargarsi, un peso non nullo
al contrario consentirà alla 0
colonna di allargarsi.
Maggiore il peso, maggiore
lo spazio occupato dalla riga
o dalla colonna. 1

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


0 1 0

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 1 0

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


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:

0 1 0

Se il componente non sfrutta tutta l’area della cella, può essere


posizionato in modo diverso al suo intero:

NorthWest North NorthEast


West Center East
SouthWest South SouthEast

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 1 0

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


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”));

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


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”)).

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


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()

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


Esempio

Si costruisca una finestra come la seguente:

Per prima cosa, individuiamo righe, colonne e pesi:

0 1

0
0
0

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


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);

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


Reazione del pannello ai ridimensionamenti:

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


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)

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


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);
}
}

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


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.

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


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) {


...
}
}

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


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.

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


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);
}
}

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


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();
}

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

Potrebbero piacerti anche