LINGUAGGI E TRADUTTORI
RELAZIONE N° 5
QUIETI FABIO
Descrizione del problema
Questa esperienza riguarda la grafica in java, ovvero lo studio del package grafico swing. In
particolare si vogliono creare due finestre, simili, infatti la seconda deriva dalla prima con
l’aggiunta di qualche elemento.
Analisi
La prima finestra che si vuole creare deve essere centrata nello schermo e di dimensioni fisse; deve
avere una crocetta al centro (10x10) e un bottone in basso al centro, che verrà chiamato Quit e
premendo il quale la finestra si chiude. Nella seconda finestra si aggiungono alla prima quattro
pulsanti in basso a sinistra (Up, Down, Left e Right, spostando Quit a destra), premendo i quali la
crocetta si deve spostare, nella direzione corrispondente al tasto premuto, di un intervallo di griglia,
che verrà visualizzato in alto e che può essere settato da tastiera.
Progetto
La prima finestra che si vuole creare è definita nella classe Window1 che è un componente
software, infatti contiene il main. Come in tutte le classi che si definiranno in questa esperienza si
devono importare i package awt, swing e awt.event, quest’ultimo solo se si devono definire dei
componenti attivi che generano eventi, come nel caso del bottone quit premendo il quale si deve
chiudere la finestra. In questo main di Window1 si definisce e si crea subito il JFrame f dandogli
come titolo proprio Window1. Quindi si definiscono posizione del vertice alto sinistro e dimensioni
di f con il metodo setBounds. Creato il JFrame opportuno viene richiamato il suo container, c, con il
metodo getContentPane. Infatti è al container che va aggiunto il pannello sul quale disegnare e al
quale aggiungere i nostri componenti. Quindi si crea un nuovo oggetto JPanel p e si setta il suo
layout come BorderLayout. Questo verra aggiunto a c alla fine con il comando add. Al JPanel p
vengono aggiunti due pannelli: il primo (panel) è un oggetto MyPanel di una nuova classe che
estende JPanel, che viene aggiunto con un BorderLayout.CENTER, quindi centrato nel JFrame; il
secondo (pbutt) è un Jpanel che viene aggiunto a p con un BoederLayout.SOUTH, quindi nella
parte bassa del JFrame. A pbutt viene aggiunto inoltre q, un oggetto MyButton che è una classe che
estende JButton.
Infine viene aggiunto al frame f WindowListener per gestire la chiusura e l’uscita dall’applicazione
della finestra con la classe Terminator nella quale viene definito il metodo WindowClosing con
System.exit(0).
Nella classe MyPanel troviamo la ridefinizione di paintComponent che mi permette di disegnare il
pannello grazie alle istruzioni passate al Graphics g. Si hanno due drawLine per disegnare la
crocetta con le coordinate opportune in modo che sia centrata e 10x10 pixel. Inoltre vi è il comando
setBackground(Color.white) che mi definisce il colore dello sfondo bianco.
L’altra classe MyButton è quella che mi definisce Quit. Questa classe oltre che estendere JPanel
deve implementare anche ActionListener in quanto vi è un evento generato da Quit. Troviamo il
costruttore nel quale viene creato il JButton b con etichetta “Quit”, e il quale è ascoltatore degli
eventi da esso stesso generati con il comando b.addActionListener(this). Il this indica appunto che è
il bottone b stesso che registra gli eventi. Quindi viene aggiunto il JButton b con la solita add.
Inoltre vi è un metodo che gestice l’evento ovvero actionPerformed; questo metodo è definito da
System.exit(0) in quanto con la pressione del tasto Quit si voleva chiudere la finestra.
La classe Window2 è quella che definisce la seconda finestra; rispetto al main di Window1
troviamo in più: tpanel, un oggetto TextPanel che è sempre una nuova classe derivata da JPanel.
Questo viene aggiunto al pannello principale p con BorderLayout.NORTH; sarà il pannello che mi
definisce la griglia modificabile da tastiera. Il pannello della zona centrale è cambiato e viene
definito nella nuova classe NewPanel. Quindi notiamo che il pannello pbutt viene settato con
BorderLayout: infatti gli vengono aggiunti il Mybutton q con BorderLayout.EAST e un
ButtonPanel (bpanel) con BorderLayout.WEST. La nuova classe ButtonPanel sarà quella che mi
definisce i nuovi quattro tasti.
La classe TextPanel estende JPanel e implementa ActionListener in quanto si registra il
cambiamento del valore della griglia con la pressione del tasto invio. Vi è il costruttore nel quale
viene creata la JLabel l “Griglia” e aggiunta con add; quindi viene creato il campo di testo editabile
JTextField text di lunghezza 5, il quale è anche l’ascoltatore degli eventi da esso generati
(text.addActionListener(this)), infine viene aggiunto anche text. Vi è poi un primo metodo che è il
solito actionPerformed nel quale il valore di text, ottenuto con getText( ), viene convertito in intero
e assegnato alla variabile D, che verrà utilizzata per definire gli eventi dei nuovi tasti. L’ultimo
metodo (getD( )) serve proprio per avere il valore settato della griglia, infatti restituisce un intero ed
è definito da return D.
Anche la nuova classe ButtonPanel estende JPanel e implementa ActionListener. Il costruttore ha
due parametri: un NewPanel e un TextPanel. Chiaramente quelli passati in Window2 sono quelli
che si sono definiti e creati. Nel costruttore troviamo la creazione dei quattro JButton (up, down,
left, right) ognuno con la propria etichetta; quindi ognuno è anche definito come ascoltatore dei
propri eventi e infine vengono tutti aggiunti. Quindi troviamo il solito metodo che gestisce gli
eventi actionPerformed: viene assegnato all’oggetto pushedbutton il tasto premuto con
e.getSource ( ), dove e è l’evento; quindi con degli if viene controllato quale tasto è stato premuto
uguagliando pushedbutton ad up, a down, ecc. Per ogni tasto viene controllato che la crocetta non
esca dalla finestra sommando o aggiungendo il valore di D (ottenuto con getD) al valore corrente
delle variabili x o y. Se così fosse viene bloccato il valore della variabile corrispondente (x o y),
altrimenti viene aggiornato il valore stesso. Infine troviamo due metodi (getx( ) e gety( )) che mi
danno i valori delle corrispondenti variabili per poter dare le coordinate per ridisegnare la crocetta.
L’ultima classe che estende JPanel è NewPanel; in questa troviamo sempre la ridefinizione di
paintComponent come in MyPanel. Viene sempre settato il colore dello sfondo bianco e vi sono
quindi due drawLine, dove però le coordinate sono date dai metodi getx e gety richiamati su un
ButtonPanel che viene settato con il metodo setButtonPanel. Quindi in Window2 vi sarà anche
l’istruzione panel.setButtonPanel(bpanel).
Implementazione
Classe Window1
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Window1 {
public static void main(String[] v){
JFrame f = new JFrame("Window 1");
f.setBounds(200,100,400,400);
Container c = f.getContentPane();
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
MyPanel panel = new MyPanel();
p.add(panel, BorderLayout.CENTER);
JPanel pbutt = new JPanel();
MyButton q = new MyButton();
pbutt.add(q);
p.add(pbutt, BorderLayout.SOUTH);
c.add(p);
f.addWindowListener(new Terminator());
f.show();
}
}
Classe MyPanel
import java.awt.*;
import javax.swing.*;
public class MyPanel extends JPanel{
public void paintComponent( Graphics g){
super.paintComponent (g);
setBackground(Color.white);
g.drawLine(200,195,200,205);
g.drawLine(195,200,205,200);
}
}
Classe MyButton
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MyButton extends JPanel implements ActionListener {
public MyButton() {
super();
JButton b=new JButton("Quit");
b.addActionListener(this);
add(b);
}
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
Classe Window2
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Window2 {
public static void main(String[] v){
JFrame f = new JFrame("Window 2");
f.setBounds(200,100,400,400);
Container c = f.getContentPane();
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
TextPanel tpanel = new TextPanel();
p.add(tpanel, BorderLayout.NORTH);
NewPanel panel = new NewPanel();
panel.setButtonPanel(bpanel);
p.add(panel, BorderLayout.CENTER);
JPanel pbutt = new JPanel();
p.add(pbutt, BorderLayout.SOUTH);
pbutt.setLayout(new BorderLayout());
MyButton q = new MyButton();
ButtonPanel bpanel = new ButtonPanel();
panel.setButtonPanel(bpanel);
pbutt.add(q, BorderLayout.EAST);
pbutt.add(bpanel, BorderLayout.WEST);
c.add(p);
f.addWindowListener(new Terminator());
f.show();
}
}
Classe TextPanel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TextPanel extends JPanel implements ActionListener {
JtextField text;
int D;
public TextPanel() {
super();
JLabel l = new JLabel("Griglia:");
add(l);
text = new JTextField(5);
text.addActionListener(this);
add(text);
}
public void actionPerformed(ActionEvent e) {
D = Integer.parseInt(text.getText());
}
public int getD() {
return D;
}
}
Classe ButtonPanel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ButtonPanel extends JPanel implements ActionListener {
JButton up,down,left,right;
TextPanel t;
NewPanel p;
int x=200, y=200;
public ButtonPanel(TextPanel tp, NewPanel mp) {
super();
t=tp;
p=mp;
up = new JButton("Up");
down = new JButton("Down");
left = new JButton("Left");
right = new JButton("Right");
left.addActionListener(this);
right.addActionListener(this);
up.addActionListener(this);
down.addActionListener(this);
add(left);
add(right);
add(up);
add(down);
}
public void actionPerformed(ActionEvent e) {
Object pushedbutton = e.getSource();
if(pushedbutton==up) {
if((y-t.getD())<5) y=5;
else y=y-t.getD();
p.repaint();
}
if(pushedbutton==down) {
if((y+t.getD())>395) y=395;
else y=y+t.getD();
p.repaint();
}
if(pushedbutton==left) {
if((x-t.getD())<5) y=5;
else x=x-t.getD();
p.repaint();
}
if(pushedbutton==right) {
if((x+t.getD())>395) y=395;
else x=x+t.getD();
p.repaint();
}
}
public int getx() {
return x;
}
public int gety() {
return y;
}
}
Classe NewPanel
import java.awt.*;
import javax.swing.*;
public class NewPanel extends JPanel{
ButtonPanel bp;
public void paintComponent( Graphics g){
super.paintComponent (g);
setBackground(Color.white);
g.drawLine(bp.getx(),bp.gety()-5,bp.getx(),bp.gety()+5);
g.drawLine(bp.getx()-5,bp.gety(),bp.getx()+5,bp.gety());
}
public void setButtonPanel(ButtonPanel bpanel) {
bp=bpanel;
}
}
Casi d’uso
La seguente immagine mostra la prima finestra creata:
La seguente immagine mostra invece la seconda finestra creata modificando la prima:
Concetti e tecniche acquisiti
Questa esecrcitazione è servita per conoscere e prendere confidenza con la grafica in java, ovvero il
package swing con tutte le sue classi. Inoltre si è imparato un nuovo metodo per progammare: non
più elaborazione dei dati in ingresso con in uscita i risultati, ma programmazione event-driven, di
reazione a eventi generati da i componenti grafici detti attivi, tipo un tasto quando viene premuto. In
particolare ho imparato che il JFrame è il componente usato per disegnare una finestra con un titolo
con delle dimensioni a piacere. Poi che il JPanel è quello su cui disegnare e sul quale aggiungere
altri componenti, anche altri pannelli, magari creati a proprio bisogno estendendo JPanel. Per avere
una disposizione grafica esatta come pare a noi si deve specificare il layout di un pannello. Un
pannello va sempre aggiunto al container del frame che lo contiene, come ogni altro componente
contenuto in un pannello va aggiunto al pannello stesso. I componenti incontrati nell’esercitazione
oltre al JPanel sono il JButton, il JTextField e il JLabel. Si è visto come per un componente attivo,
come i tasti usati, la classe che li definisce deve implementare una interfaccia che contiene il
metodo per la gestione dell’evento; inoltre va specificato anche un componente ascoltatore degli
eventi, che nei casi dell’esercitazione sono sempre i componenti stessi che generano l’evento.