RELAZIONE 5 : JAVA E LA GRAFICA
Lo scopo di questa esercitazione è quello di realizzare applicazioni grafiche in Java. Java permette
di rendere la grafica “interattiva”, cioè in grado di compiere diverse azioni a seconda degli ordini
impartiti di volta in volta dall’utente.
Java dispone di una libreria ( Swing ), che definisce una gerarchia di classi che forniscono
ogni tipo di componente grafico. Di conseguenza, per creare una grafica personalizzata, spesso
basta estendere classi già esistenti.
Descrizione del problema
Si chiede di:
- implementare un frame ( una finestra ), partendo dalla classe JFrame di Swing, centrato
nello schermo e di grandezza 400x400 pixel;
- gestire la chiusura della finestra mediante un pulsante di Quit;
- porre al centro della finestra un puntatore a crocetta;
- il puntatore si deve poter muovere all’interno di una “griglia”;
- il puntatore deve essere sensibile al click del mouse e controllabile tramite quattro pulsanti
di movimento ( Up, Down, Left, Right );
- la grandezza dello spostamento dato dai pulsanti di movimento deve essere controllata
mediante un campo di testo;
- evitare di far uscire la crocetta dai margini della griglia.
Analisi
Questa esercitazione ci consentirà di familiarizzare con una programmazione “event-driven”, in cui
il comportamento dei componenti creati è condizionato dalle azioni dell’utente sui componenti
stessi.
Inoltre ci permetterà di prendere confidenza con una classe predefinita, e di imparare a
sfruttare a pieno le potenzialità del linguaggio, senza dover partire da zero nella creazione dei
componenti grafici. Java ci offre infatti una sorta di “percorso guidato” che è conveniente sfruttare.
Progetto: come risolvere il problema
Per creare un’interfaccia grafica completa ed efficace non basta un singolo gestore di Layout,
conviene suddividere l’area da trattare in zone, corrispondenti ad altrettanti pannelli, e applicare a
ogni zona il Layout manager più opportuno.
Zone:
- Center : che conterrà la griglia con al centro il cursore. Questa griglia rappresenta lo spazio
limite di movimento del cursore.
- South : che è a sua volta diviso in due parti:
o la prima contiene il pulsante di Quit, che fa chiudere la finestra ;
o la seconda contiene i quattro pulsanti che comandano il movimento del cursore.
- Noth: che conterrà una casella di testo per contenere le istruzioni per la grandezza degli
spostamenti del cursore.
Il risultato sarà più o meno questo:
GRIGLIA
QUIT
Tutti i pannelli usati si appoggiano su un pannello principale che li contiene tutti e che fa da
ascoltatore (nel caso di pannelli con ascoltatore esterno). In modo semplicistico si può pensare ad
un pannello “padre”, che tiene d’occhio e accoglie tutti i pannelli figli.
Descrizione delle classi e dei metodi usati






MyFrame: classe che estende il componente predefinito JFrame (che crea una finestra ): il
metodo Toolkit.getDefautToolkit().getScreenSize mi permette di ottenere le dimensioni dello
schermo, il metodo setBound mi permette di fissare posizione e dimensioni del Frame.
Contiene un costruttore che accetta come parametro in entrata un Layout Manager.
MyPanel1: classe che crea un pannello personalizzato che estende quello di deauft (JPanel).
Dentro al pannello viene posto il bottone Quit ( mediante il metodo add ) e il pannello stesso
è designato ad ascoltatore del bottone. Per poter fungere da ascoltatore, MyPanel1 deve
implementare l’interfaccia ActionListener e usare il metodo addActionListener (this).
Contiene un costruttore che accetta come parametro in entrata un Layout Manager.
MyPanel2: classe che crea un pannello personalizzato che estende quello di deauft (JPanel).
Crea quattro pulsanti (JButton u=new JButton (“Up”)) per il controllo dei movimenti del
cursore ( Up, Down, Left, Right ). L’ascoltatore è esterno al pannello e definito con
exList=externalListener.
Contiene un costruttore che accetta come parametro in entrata un Layout Manager.
FielPanel: crea il pannello che contiene una piccola “finestra di scrittura”, che conterrà il
valore del passo degli spostamenti del cursore. Con un ciclo try-catch si controlla siano scritti
solo numeri. Contiene un costruttore che accetta come parametro in entrata un Layout
Manager.
MyCenterPanel: è il pannello centrale, deve gestire una griglia che rappresenta lo spazio di
movimento del cursore. Inizialmente il cursore a crocetta deve essere disegnato nel centro.
MyCenterPanel necessita di due ascoltatori esterni ( il costruttore public MyCenterPanel
accetta in entrata due parametri), uno per reagire agli spostamenti del mouse, l’altro per
controllare che il cursore non superi i limiti imposti. Vengono implementati i metodi per
settare e leggere la posizione del cursore ( setPosition, GetPosition ) e per disegnare il cursore
(paintComponent).
DadPanel: è il pannello padre, su cui si appoggiano gli altri pannelli. Al suo interno i pannelli
vengono richiamati con il costruttore che accetta come parametro di entrata il Layout
opportuno. Il pannello padre fa da ascoltatore quando:
o vengono usati i bottoni di movimento ( public void actionPerformed );
o viene usato il mouse ( public void mouseClick ).

Terminator : classe che implementa l’interfaccia WindowListener, in modo che
WindowClosing invochi System.exit().
 PersonalFrame: è il componente Software che mi permette di testare i componenti creati.
Implementazione
MyFrame
import java.awt.*;
import javax.swing.*;
public class MyFrame extends JFrame {
public MyFrame (int x, int y) {
super();
Dimension d =Toolkit.getDefaultToolkit().getScreenSize();
int xc=d.height/2;
int yc=d.width/2;
/* Setto le dimensioni del frame*/
setBounds(xc-x/2,yc-y/2,x,y);
}
}
/*
*Il frame che devo usare non ha titolo
*/
MyPanel1
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MyPanel1 extends JPanel implements ActionListener {
/*costruttore
*/
public MyPanel1() {
super();
JButton b=new JButton("Quit");
b.addActionListener(this);
add(b);
}
public void actionPerformed (ActionEvent e) {
System.exit(0);
}
/* aggiungo un costruttore che accetti in entrata un parametro
* per la gestione del LayoutManager
*/
public MyPanel1(LayoutManager lm) {
super(lm);
JButton b=new JButton("Quit");
b.addActionListener(this);
add(b);
}
}
MyPanel2
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MyPanel2 extends JPanel {
ActionListener exList;
/*costruttore*/
public MyPanel2(ActionListener externalActionListener) {
super();
/*ascoltatore esterno*/
exList= externalActionListener;
/* creazione bottoni aggiunta dei bottoni al pannelo*/
JButton u=new JButton("Up");
add(u);
JButton d=new JButton("Down");
add(d);
JButton l=new JButton("Left");
add(l);
JButton r=new JButton("Right");
add(r);
/* associo ai bottoni creati l'ascoltatore esterno*/
u.addActionListener(exList);
d.addActionListener(exList);
l.addActionListener(exList);
r.addActionListener(exList);
}
/* definisco un altro costruttore che accetta come parametro in entrata
* un LayoutManager
* per il resto è uguale al costruttore sopra
*/
public MyPanel2(ActionListener externalActionListener,LayoutManager lm) {
super(lm);
exList= externalActionListener;
JButton u=new JButton("Up");
add(u);
JButton d=new JButton("Down");
add(d);
JButton l=new JButton("Left");
add(l);
JButton r=new JButton("Right");
add(r);
u.addActionListener(exList);
d.addActionListener(exList);
l.addActionListener(exList);
r.addActionListener(exList);
}
}
FieldPanel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class FieldPanel extends JPanel implements ActionListener {
JTextField tf;
int max;
int num;
public FieldPanel () {
super();
tf=new JTextField(5);
tf.addActionListener(this);
add(tf);
max=100;
num=0;
}
/* aggiungo un costruttore con un parametro per la gestione del Layout
*/
public FieldPanel (LayoutManager lm) {
super(lm);
tf=new JTextField(5);
tf.addActionListener(this);
add(tf);
max=100;
num=0;
}
/*Controllo errori*/
public void actionPerformed(ActionEvent ae) {
int n;
try {
n=Integer.parseInt(tf.getText());
if (n>max) {
tf.setText(" ");
tf.setText(" "+num);
repaint();
}
else {
num=n;
}
}
catch (NumberFormatException nfe) {
tf.setText(" ");
tf.setText(" "+num);
repaint();
}
}
/*Lettura del valore del field*/
public int getValue() {
return num;
}
}
MyCenterPanel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class MyCenterPanel extends JPanel {
MouseListener mouse;
int px,
py,
ox,
oy,
rx,
ry,
sx,
sy;
public MyCenterPanel (MouseListener externalMouseListener,Rectangle rectpad) {
super();
setBackground(Color.white);
/* ascoltatore per il muose*/
mouse=externalMouseListener;
addMouseListener(mouse);
ox=px;
oy=py;
rx=rectpad.x;
ry=rectpad.y;
sx=rectpad.width;
sy=rectpad.height;
px=rx+sx/2;
py=ry+sy/2;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
/* disegno griglia*/
g.setColor(Color.lightGray);
g.drawRect(rx,ry,sx,sy);
/*disegno cursore a crocetta*/
g.setColor(Color.black);
g.drawLine(px-5,py,px+5,py);
g.drawLine(px,py-5,px,py+5);
}
/*Setto la posizione del cursore*/
public void setPosition(int xPosition, int yPosition) {
if ((xPosition>rx)&&(yPosition>ry)&&(xPosition<rx+sx)&&(yPosition<ry+sy)) {
px=xPosition;
py=yPosition;
repaint();
}
}
/*Leggo la posizione del cursore*/
public int getPositionX(){
return px;
}
public int getPositionY(){
return py;
}
}
DadPanel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class DadPanel extends JPanel implements ActionListener, MouseListener {
/*variabili private */
MyPanel1 mPanel;
MyPanel2 mdPanel;
MyCenterPanel mcPanel;
FieldPanel fPanel;
int step;
public DadPanel() {
super();
setLayout(new BorderLayout());
JPanel southPanel=new JPanel();
JPanel northPanel=new JPanel();
southPanel.setLayout(new BorderLayout());
northPanel.setLayout(new BorderLayout());
FlowLayout fLayout=new FlowLayout();
fLayout.setAlignment(FlowLayout.LEFT);
/*South*/
mdPanel=new MyPanel2(this,fLayout);
southPanel.add(mdPanel,BorderLayout.WEST);
fLayout.setAlignment(FlowLayout.RIGHT);
mPanel=new MyPanel1(fLayout);
southPanel.add(mPanel,BorderLayout.EAST);
add(southPanel,BorderLayout.SOUTH);
/*North*/
fLayout.setAlignment(FlowLayout.RIGHT);
fPanel=new FieldPanel(fLayout);
northPanel.add(fPanel,BorderLayout.EAST);
add(northPanel,BorderLayout.NORTH);
/*Center*/
Rectangle CenterDimension=new Rectangle(10,10,370,280);
mcPanel=new MyCenterPanel(this,CenterDimension);
add(mcPanel,BorderLayout.CENTER);
/*Setto il passo degli spostamenti*/
step=fPanel.getValue();
}
/*Ascoltare per i bottoni di movimento*/
public void actionPerformed(ActionEvent ae) {
step=fPanel.getValue();
String argButton=ae.getActionCommand();
if ("Up".equals(argButton)){
mcPanel.setPosition(mcPanel.getPositionX(),mcPanel.getPositionY()-step);
}
if ("Down".equals(argButton)){
mcPanel.setPosition(mcPanel.getPositionX(),mcPanel.getPositionY()+step);
}
if ("Left".equals(argButton)){
mcPanel.setPosition(mcPanel.getPositionX()-step,mcPanel.getPositionY());
}
if ("Right".equals(argButton)){
mcPanel.setPosition(mcPanel.getPositionX()+step,mcPanel.getPositionY());
}
}
/*Ascoltatore per il muose*/
public void mouseClicked(MouseEvent me) {
mcPanel.setPosition(me.getX(),me.getY());
}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me) {}
public void mousePressed(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {}
}
Terminator
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Terminator implements WindowListener {
/* devo implementare formalmente tutti i metodi dell'intefaccia
* anche se non tutti mi servono realmente
*/
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated (WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
PersonalFrame
/* Componente SW*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class PersonalFrame {
public static void main (String[] args) {
DadPanel dPanel = new DadPanel();
MyFrame mFrame = new MyFrame(400,400);
mFrame.addWindowListener(new Terminator());
Container mFrameContainer=mFrame.getContentPane();
mFrameContainer.add(dPanel);
mFrame.show();
}
}
Concetti appresi
Con questa esercitazione ho imparato a creare e gestire applicazioni grafiche, sfruttando un insieme
di classi che Java mette a disposizione. Ancora una volta va sottolineata l’importanza delle
astrazioni e delle gerarchie che permettono di sfruttare al meglio le potenzialità del linguaggio.
Per quanto riguarda gli elementi di grafica, ho lavorato con gli elementi base (finestre,
pannelli, bottoni …) e ho imparato a gestirne gli ascoltatori. Già con questi pochi elementi si può
creare una grafica piacevole e interattiva.