|
Organitzant una finestra |
|
|
|
Aquesta pràctica té com a objectiu
aprendre a programar la disposició
dels controls en una finestra, és
a dir, a programar la disposició
dels elements que formaran la interfície
gràfica d'usuari GUI (Graphics
User Interface) mitjançant la qual els usuaris
de les nostres aplicacions poden interactuar
amb elles, fer-les servir, vaja.
- Es discuteix la noció, propia de Java,
de layout manager i se'n presenten
tres exemples i el seu ús. També s'ensenya com combinar
diversos layout managers per tal d'obtenir
estructures més complexes.
- Es presenta i s'ensenya l'ús del control
més senzill: el label
(etiqueta amb text)
i, de passada, es fa una introducció al maneig del color.
- Finalment, s'introdueixen tres controls
més, els botons i els dos associats
a textos editables, encara que es reserva
el treball sobre les seves funcionalitats per a pràctiques posteriors.
|
|
|
|
Desenvolupament de la pràctica |
|
|
|
La finestra base o finestra
arrel que hem après a construir a la pràctica anterior
ja té tota la funcionalitat necessària per tal de rebre
i disposar els controls que han de constituir
l'interfície gràfica, la
GUI, de les nostres aplicacions.
La classe java.awt.Frame
deriva de java.awt.Container, és a dir,
és un contenidor (container)
cosa que vol dir que està preparada per emmagatzemar components
(derivats de java.awt.Component)
i, a més, incorpora una estructura
(layout) la qual s'encarregarà
de gestionar la disposició d'aquests components a la pantalla.
|
|
|
|
Els "layouts" |
|
|
 |
"Write once, run anywhere". Ja hem dit que una
aplicació Java ha de ser independent
del maquinari. I això té
molta importància aquí: la GUI
de les nostres aplicacions no pot pressuposar res,per exemple,sobre
el tamany o la resolució
en píxels de la pantalla del ordinador
en la qual s'executaran. Per tant, no es una bona cosa pensar: "Vull
un botó de 90 x 40 a la posició 145, 230" i, de fet,
les classes de l'AWT
ja s'encarreguen d'impedir tan com poden que el programador se'n surti
si pensa les coses així...
Cal aprendre a pensar en termes de "layouts".
Un layout és un esquema general
de disposició a la pantalla dels components
d'un contenidor. El
layout manager s'encarrega automàticament de donar les dimensions
adequades als components i d'alinear-los
segons les disponibilitats.
L'AWT ens proporciona aquests layout
managers:
- java.awt.BorderLayout
- java.awt.CardLayout
- java.awt.FlowLayout
- java.awt.GridBagLayout
- java.awt.GridLayout
dels quals us invitem a veure'n la documentació
ara mateix.
Conclusió:
Si volem disposar elements per a una GUI,
aquests elements han de ser derivats
de la classe java.awt.Component,
o d'alguna de les seves classes filles
(tots els controls ho són!). El
lloc per disposar-los ha de ser una classe derivada
de java.awt.Container (o d'alguna de les seves
classes filles) provista del layout
manager que més s'adigui als desitjos del programador.
Per a usos corrents, el contenidor adequat
és gairebé sempre la classe
java.awt.Panel.
|
|
|
|
Comencem! |
|
|
 |
Començarem posant uns quants labels
(etiquetes de text) distribuïts
per la nostra finestra. Iniciem un nou projecte,
Layouts01, (definiu-lo com a "Basic
Java Application"), i després de comentar
la línia package myprojects.Layouts01;,
modifiqueu el codi que JCreator ha posat
en el fitxer Layouts01.java. Les parts a modificar
estan en color groc clar:
/*
* @(#)Layouts01.java 1.0 02/09/13
*
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_1\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/ |
//package myprojects.Layouts01; |
import java.awt.*;
import java.awt.event.*;
class Layouts01 extends
Frame {
public Layouts01()
{
addWindowListener(new
WindowAdapter() {
public
void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
public static void
main(String args[]) {
System.out.println("Starting
Layouts01...");
Layouts01 mainFrame
= new Layouts01();
mainFrame.setSize(400,
400);
|
mainFrame.setTitle("Cinc
Labels en BorderLayout");
Label label_1=new
Label("Això és el primer 'Label'");
label_1.setAlignment(Label.CENTER);
Label
label_2=new Label("Això és el segon 'Label'");
label_2.setBackground(Color.YELLOW);
label_2.setAlignment(Label.CENTER);
Label
label_3=new Label("Això és el tercer 'Label'");
label_3.setBackground(Color.BLUE);
label_3.setForeground(Color.WHITE);
label_3.setAlignment(Label.CENTER);
Label
label_4=new Label("Això és el quart 'Label'");
label_4.setBackground(Color.CYAN);
label_4.setAlignment(Label.CENTER);
Label
label_5=new Label("Això és el cinquè 'Label'");
label_5.setBackground(Color.BLACK);
label_5.setForeground(Color.PINK);
label_5.setAlignment(Label.CENTER);
mainFrame.add(label_1,BorderLayout.NORTH);
mainFrame.add(label_2,BorderLayout.SOUTH);
mainFrame.add(label_3,BorderLayout.EAST);
mainFrame.add(label_4,BorderLayout.WEST);
mainFrame.add(label_5,BorderLayout.CENTER);
|
mainFrame.setVisible(true);
}
} |
|
|
|
|
El resultat ha de ser aquest: |
|
|
|
|
|
|
|
Vegem què hem fet: |
|
|
 |
- Hem construït cinc instàncies
del control
java.awt.Label, que és el control
més senzill que hi ha: la seva única funcionalitat és
la de mostrar un text. Consulteu-ne la documentació
per veure'n els mètodes constructors.
En els cinc casos, hem fet servir el mètode
constructor public
Label(String text) i, com ja es pot suposar,
el paràmetre
text és el
text que el label ha
de mostrar-nos.
- Si, com en el cas de label_1
(el nom "label_1"
és arbitrari, clar!) no fem cap altra especificació, el
color del fons
(background),
el dels caràcters
del text (foreground)
i la font
són els del contenidor
on hem posat el component.
Al nostre cas, el Frame
(la finestra) era de fons blanc i si hi haguéssim escrit alguna
cosa, el text hagués estat negre. Aquesta és doncs, la
presentació de label_1.
En canvi, als altres labels
hi hem fet modificacions mitjançant els mètodes
public void setForeground(Color color)
i public void setBackground(Color color),
de la classe mare
de Label,
java.awt.Component.
- A
Java tot són classes
i no podia ésser d'altra manera amb el color! Examineu ara la
documentació
de la classe
java.awt.Color.
Si volem obtenir un determinat color podem acudir directament a les
variables
static
Color.BLACK
Color.BLUE
Color.CYAN
Color.DARK_GRAY
Color.GRAY
Color.GREEN
Color.LIGHT_GRAY
Color.MAGENTA
Color.ORANGE
Color.PINK
Color.RED
Color.WHITE
Color.YELLOW
o bé, construir el color RGB
amb algun dels mètodes constructors
de java.awt.Color.
Per exemple, podeu substituir la línia
label_3.setBackground(Color.BLUE); |
per
label_3.setBackground(new Color(0,0,255)); |
i, tot canviant els paràmetres,
veure'n els resultats.
- Si per causa de l'actuació del layout
manager algun label
és més ample que el text que mostra,
llavors és important determinar-ne l'alineament.
Tenim disponibles les variables
static de java.awt.Label
següents:
Label.CENTER
Label.LEFT
Label.RIGHT
i el mètode
public void setAlignment(int alignment).
Podeu fer proves, canviar els alineaments
dels labels 1,
2 4 i 5 i pensar perquè en uns casos hi ha canvis i en d'altres
no..
- Finalment, els cinc labels
s'han disposat així dins del contenidor
(la finestra) precisament perquè, per defecte, java.awt.Frame
porta incorporat el layout manager
java.awt.BorderLayout. Aquest layout
manager admet fins a cinc components
i els disposa així:
i, si volem afegir els nostres components,
els nostres labels,
cal fer servir el mètode public
void add(Component component,String position).
El paràmetre position
és una de les cinc variables
static:
BorderLayout.NORTH
BorderLayout.SOUTH
BorderLayout.EAST
BorderLayout.WEST
BorderLayout.CENTER
- Per veure el funcionalent de java.awt.BorderLayout,
retallem ara una mica el text dels labels
i deixem-los així:
Label label_1=new
Label("N");
Label label_2=new Label("S");
Label label_3=new Label("E");
Label label_4=new Label("W");
Label label_5=new Label("C"); |
El resultat és:
i ens mostren que:
- les dimensions
del label s'adapten a les necessitats:
un label
té les dimensions mínimes per tal que hi càpiga
el text que ha de mostrar
- java.awt.BorderLayout
ignora les dimensions horitzontals
dels components
situats a "north"
i "south",
però en respecta les verticals.
- java.awt.BorderLayout ignora
les dimensions verticals
dels components
situats a "east"
i "west",
però en respecta les horitzontals.
- java.awt.BorderLayout
ignora tant les dimensions horitzontals
com les verticals
del component
situat a "center".
Encara ens en podem convèncer més si
modifiquem les dimensions de la finestra, canviant els paràmetres
a la línia
mainFrame.setSize(400, 400); |
|
|
Més layouts: |
|
|
 |
java.awt.BorderLayout és el layout
manager per defecte de java.awt.Frame,
però podem canviar-lo. Inmediatament després de la línia
Layouts01 mainFrame = new Layouts01(); |
insertem la línia:
mainFrame.setLayout(new FlowLayout()); |
la qual determina que ara mainFrame té
una instància de
java.awt.FlowLayout com a layout manager.
També cal que canviem les línies
mainFrame.add(label_1,BorderLayout.NORTH);
mainFrame.add(label_2,BorderLayout.SOUTH);
mainFrame.add(label_3,BorderLayout.EAST);
mainFrame.add(label_4,BorderLayout.WEST);
mainFrame.add(label_5,BorderLayout.CENTER);
|
per les línies:
mainFrame.add(label_1);
mainFrame.add(label_2);
mainFrame.add(label_3);
mainFrame.add(label_4);
mainFrame.add(label_5);
|
i si volem ser coherents, canviem el títol
de la finestra:
mainFrame.setTitle("Cinc Labels en FlowLayout"); |
Per veure'n bé l'efecte, fem que els respectius textos dels labels
tinguin longituds variades, per exemple:
Label label_1=new Label("Aquest era el Label
del Nord");
Label label_2=new Label("I aquest el del Sud");
Label label_3=new Label("Era del Est");
Label label_4=new Label("Del Oest");
Label label_5=new Label("Era el Label del Centre");
|
El resultat és:
|
|
|
|
Com funciona el FlowLayout? |
|
|
 |
- Les dimensions,
tant horitzontals
com verticals,
dels components
es respecten.
- Els components es disposen
cadascun a continuació de l'anterior, de la mateixa maneraque
les paraules sobre un text. Quan s'esgota l'espai horitzontal, s'inicia
una nova línia.
|
|
|
|
Un altre layout:
|
|
|
 |
Finalment, discutirem el layout
manager java.awt.GridLayout.
Només cal modificar la línia
mainFrame.setLayout(new FlowLayout()); |
amb:
mainFrame.setLayout(new GridLayout(3,2)); |
(i la de mainFrame.setTitle(
... ))
Obtenim:
Si ara canviem new GridLayout(3,2)
per new GridLayout(4,2) obtenim:
tot mostrant que:
- el layout
manager java.awt.GridLayout
disposa els components
en una matriu rectangular de files
files i columnes
columnes. El mètode constructor
és: public GridLayout(int files,int
columnes).
- No es respecta cap de les dimensions
dels components.
Les dimensions es forcen per tal que totes les cel·les de la
matriu siguin iguals
|
|
|
|
Combinant layouts... |
|
|
 |
Naturalment, aquests layout managers
es poden combinar per donar lloc a estructures més complexes. La
classe java.awt.Panel
és filla de java.awt.Container,
la qual és filla de java.awt.Component.
Per tant, java.awt.Panel és un contenidor
(pot admetre components) i també
és un component i, per tant, pot
ser incorporat a un contenidor. Això
vol dir que podem prendre una instància
de java.awt.Panel, dotar-la del layout
manager que ens interessi (per defecte és java.awt.FlowLayout)
posar-hi els components que calgui i
posar-ho tot plegat com a component a
la nostra finestra, que ja tindrà el seu propi layout
manager.
|
|
|
|
Un exemple de combinació: |
|
|
 |
Nou projecte,
Layouts02, (definiu-lo també com a "Basic
Java Application"): Després de comentar
la línia package myprojects.Layouts02;,
modifiqueu el codi que JCreator ha posat
en el fitxer Layouts02.java. Les parts a modificar
estan en color groc clar: |
|
|
|
/*
* @(#)Layouts02.java 1.0 02/09/15
*
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_1\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/ |
//package myprojects.Layouts02; |
import java.awt.*;
import java.awt.event.*;
class Layouts02 extends Frame {
public Layouts02() {
addWindowListener(new
WindowAdapter() {
public
void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
public static void
main(String args[]) {
System.out.println("Starting
Layouts02...");
Layouts02 mainFrame
= new Layouts02();
mainFrame.setSize(400,
400);
|
mainFrame.setLayout(new
BorderLayout());
mainFrame.setTitle("Combinació
de Layouts");
Panel
panel=new Panel();
panel.setLayout(new
GridLayout(1,5));
TextField
text_N=new TextField("Nord: hi pots escriure "+
"aquí...");
mainFrame.add(text_N,BorderLayout.NORTH);
Label
label_E=new Label("Est",Label.CENTER);
label_E.setBackground(Color.YELLOW);
label_E.setForeground(Color.BLACK);
mainFrame.add(label_E,BorderLayout.EAST);
Label
label_W=new Label("Oest",Label.CENTER);
label_W.setBackground(Color.PINK);
label_W.setForeground(Color.BLACK);
mainFrame.add(label_W,BorderLayout.WEST);
TextArea
text_C=new TextArea("Centre:\n tambe hi pots "+
"escriure
aquí...");
mainFrame.add(text_C,BorderLayout.CENTER);
Label
label_S_1=new Label("Sud 1",Label.CENTER);
label_S_1.setBackground(Color.MAGENTA);
label_S_1.setForeground(Color.YELLOW);
panel.add(label_S_1);
Button
boto_S_2=new Button("Sud 2");
panel.add(boto_S_2);
Label
label_S_3=new Label("Sud 3",Label.CENTER);
label_S_3.setBackground(Color.GREEN);
label_S_3.setForeground(Color.WHITE);
panel.add(label_S_3);
Button
boto_S_4=new Button("Sud 4");
boto_S_4.setBackground(Color.RED);
boto_S_4.setForeground(Color.BLACK);
panel.add(boto_S_4);
Label
label_S_5=new Label("Sud 5",Label.CENTER);
label_S_5.setBackground(Color.LIGHT_GRAY);
label_S_5.setForeground(Color.BLACK);
panel.add(label_S_5);
mainFrame.add(panel,BorderLayout.SOUTH);
|
mainFrame.setVisible(true);
}
} |
|
|
|
|
amb aquest resultat:
|
|
|
|
Què hi ha de nou? |
|
|
 |
- A la construcció dels labels
hem fet servir ara un altre mètode
constructor, en el qual s'hi pot especificar directament l'alineament
(vegeu la documentació de java.awt.Label).
- Per tal de trencar la monotonia i anticipar algunes coses, hem incorporat
nous controls a part dels ja coneguts
labels:
- java.awt.TextField,
que ocupa la posició "north".
Serveix per a introduir i editar textos curts d'una sola línia.
- java.awt.TextArea,
que ocupa la posició "center".
Serveix per a introduir i editar textos multilínia.
- java.awt.Button.
Dos exemplars al panel de la posició "south".
Lla funcionalitat dels quals es discutirà més endavant.
Observeu-ne els mètodes constructors
i compareu-los amb les documentacions
respectives.
- Els components que van a les posicions
"north", "center",
"east" i "west"
s'han afegit a mainFrame en la mateixa forma
que ho hem fet abans a Layouts01.
- El component que va a la posició
"south" és una instància
de java.awt.Panel, provist del layout
manager java.awt.GridLayout, d'una
fila i cinc columnes.
- Els cinc components que van a la
posició "south"
s'han afegit al contenidor
panel, el qual s'afegeix
després a mainFrame a la posició
"south"
|
|
Ara podeu experimentar amb més components
i més contenidors i fer estructures
més complexes sobre aquest mainFrame... |
|
|
|
|
|
|
 |
|
|
|
|