Sunteți pe pagina 1din 13

Distribuirea componentelor ntr-un container (Layout).

Clasele JFrame
Nu spune niciodat nu se poate, ci incepe cu s vedem.
Nicolae Iorga

Obiective:

Cuprins:

Cunoaterea modului n care controalele vor fi distribuite n cadrul


containerului Layout-ul (format predefini, respectiv aspectul
containerului) . Layout-urile existente sunt:
AWT:
BorderLayout,
FlowLayout,
CardLayout,
GridLayout,
GridBagLayout.
SWING: GroupLayout, BoxLayout. Si SpringLayout.
I. Clasele JFrame i JApplet
1.1. Proprietile i metodele clasei JFrame
1.2. Manipularea componentelor i Layout Manager.
II. Distribuirea componentelor ntr-un container
2.1. Java AWT Layouts
2.2. Java Swing Layouts

I. Clasele JFrame
Containerul de baz n care este afiat o aplicaie este clasa Frame, respectiv, n
interpretarea Swing, acea clas este JFrame motenitor al clasei java.awt.Frame.
JFrame este punctul de nceput al prii grafice din aplicaie.
Urmtorul exemplu creaz o fereastr cu dimensiunile 300 x 300 pixeli:
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.setSize(300, 300);
myFrame.setVisible(true);
}
}
1.1. Proprietile i metodele clasei JFrame
Clasa JFrame motenete o mulime de proprieti de la strmoii si, clasele Frame,
Window, Container i Component.
Constructorul clasei JFrame
JFrame mai are nc trei constructori pe lng cel default. Primul implic un parametru
de tip String. Acest parametru va reprezenta titlul din antetul ferestrei:
JFrame myFrame = new JFrame("Hello Window");
Al doilea constructor accept un parametru de tip GraphicsConfiguration i permite
emiterea ferestrei ntr-un context grafic specific (alt monitor i altele de genul acesta):
JFrame myFrame = new
JFrame(GraphicsEnvironment.getLocalGraphicsEnvironment().getSc
reenDevices()[0].getDefaultConfiguration());
Al treilea constructor accept ambii parametri menionai mai sus:

JFrame myFrame = new JFrame("Hello!",


GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDev
ices()[0].getDefaultConfiguration());
Poziionarea. Iniial, JFrame apare pe coordonatele 0,0 n relaie cu containerul printe.
Atunci cnd containerul respectiv este sistemul de operare nsui (respectiv, cnd instana
clasei JFrame este fereastra principal a aplicaiei), fereastra va aprea n colul din stnga sus
a sistemului.
Vizualizarea i modificarea poziiei pot fi efectuate prin metodele setLocation i
getLocation. n clas, locaia ferestrei este stocat n numere ntregi n cmpurile x i y. Cnd
dorim s modificm aceste valori, utilizm metoda set - setLocation. Aceast metod poate s
accepte numai numere ntregi, fiindc locaia este exprimat n pixeli (puncte pe ecran). De
asemenea, setLocation mai conine i Overload, care accept obiectul de tipul Point.
Aadar, locaia ferestrei poate fi setat n dou moduri:
myFrame.setLocation(100, 200);
sau
myFrame.setLocation(new Point(500, 500));
metoda getLocation returneaz numai valori de tip Point:
JOptionPane.showMessageDialog(myFrame,
"x:" + myFrame.getLocation().x +
" y:" + myFrame.getLocation().y );
Setarea dimensiunii. Setarea i obinerea dimensiunii ferestrei JFrame se efectueaz prin
metodele setSize i getSize. setSize accept numere ntregi (lime i nlime) ca parametrii:
myFrame.setSize(300,300);
setSize poate de asemenea s accepte un obiect de tipul Dimension
myFrame.setSize(new Dimension(300, 400));
n timpul extragerii, se utilizeaz metoda getSize, care returneaz numai obiectul de
tip Dimension:
JOptionPane.showMessageDialog(myFrame,
"width:" + myFrame.getSize().width +
" height:" + myFrame.getSize().height);
Afiarea. Fereastra nu va fi afiat pn cnd nu va fi utilizat metoda sa setVisible. Aceast
metod poate accepta un singur parametru: true i false:
...
this.setVisible(true);
...
Cnd activm metoda setVisible (care iniiaz modificarea n cmpul visible al clasei
Component), nu vom distruge fereastra, ci doar o vom ascunde. De asemenea, toate valorile
care sunt situate n ea vor fi acolo atunci cnd afim fereastra din nou, prin
metoda setVisible(true).
Dac dorim s distrugem fereastra cu adevrat, vom utiliza metoda dispose. Aceast
metod va dezactiva toate procesele din fereastr i o va nchide n condiii de siguran.
1.2. Manipularea componentelor i Layout Manager.
Pentru Jframe, la fel ca pentru toate celelalte componente, se aplic regula de adugare
a copiilor prin metoda add i eliminarea acestora prin metoda remove.
Urmtorul exemplu adaug un buton cu textul Hello n Frame-ul existent:
myFrame.add(new JButton("Hello"));
Rezultatul nu este satisfctor, deoarece actualul Layout Manager este BorderLayout:

Pentru o reprezentare valid, trebuie s setm un Layout Manager corespunztor prin


metoda setLayout.
Urmtorul exemplu modific actualul Layout Manager din BorderLayout n FlowLayout:
...
myFrame.setLayout(new FlowLayout());
myFrame.add(new JButton("Hello"));
...
Rezultatul este:

Pentru a elimina butonul adugat din fereastr, putem utiliza metoda remove. Dac
definim o component i o plasm ntr-o variabil, atunci numele variabilei poate pur i
simplu s fie expediat metodei remove:
...
JButton btn = new JButton("Hello!");
myFrame.add(btn);
...
myFrame.remove(btn);
...
n cazul n care controlul (componenta) a fost adugat anonim:
myFrame.add(new JButton("Hello!"));
trebuie s fie gsit manual i eliminat din container. De exemplu:
myFrame.remove(myFrame.getContentPane().getComponent(0));
S explicm linia precedent. Metoda myFrame.remove este clar, dar nu am
explicat getContentPane i getComponent.
i anume, n exemplul precedent este evident faptul c respectivul control este extras
din container prin indexul su din colecia de controale. ns, problema este urmtoarea: cum
s ajungem la aceea colecie?
JFrame este o fereastr care conine numai un control, containerul content pane (de
fapt, unul care este important pentru noi n acest moment). Containerele top level, precum
JFrame, conin cteva obiecte care reprezint diferite nivele, dar vom vorbi despre aceasta mai
trziu. Toate celelalte controale din fereastr sunt situate n acest container. Aceasta nseamn
c trebuie s extragem containerul mai nti, iar apoi s cutm controalele din el:
...
myFrame.getContentPane().getComponents()
for(int i=0;i<
myFrame.getContentPane().getComponentCount();i++)
myFrame.getContentPane().getComponent(i)
...
JFrame va fi rar utilizat n forma afiat, ci mult mai mult ca un ablon pentru propria
clas. Aadar, vom plasa majoritatea proprietilor acestui obiect n constructorul clasei sale.

De obicei, metoda separat (initComponents sau numai init) care efectueaz setrile
obiectului actual este apelat n interiorul constructorului. n aceast clas, vom adresa toate
setrile (metodele i proprietile) prin cuvntul cheie this:
MyFrame.java
import javax.swing.JFrame;
public class MyFrame extends JFrame {
public MyFrame()
{
initComponents();
}
void initComponents()
{
this.setSize(300, 300);
this.setVisible(true);
}
}
Program
public class Main {
public static void main(String[] args) {
MyFrame mFrame = new MyFrame();
}
}
n clasa JFrame, cu fiecare redesenare a ferestrei (dac un control trece peste aceasta
sau dac o mutm), apare activarea metodei paint, aceasta fiind, aadar, metoda n cadrul
creia putem manipula coninutul grafic al clasei:
@Override
public void paint(Graphics g) {
g.drawString("Hello", 200, 200);
}

II. Distribuirea componentelor ntr-un container


Distribuia componentelor n interiorul unui container este efectuat n conformitate cu
un format predefinit. Acest format se numete Layout, respectiv aspectul containerului. n
Swing i n AWT, exist tipuri de layout-uri predefinite (LayoutManager) pe care le putem
utiliza.
Layout este modul n care controalele vor fi distribuite n cadrul containerului. Exist
clase speciale pentru acest scop, denumite LayoutManagers, care implementeaz interfaa
LayoutManager.
Layout-urile existente sunt: BorderLayout, FlowLayout, CardLayout, GridLayout,
GridBagLayout i BoxLayout, GroupLayout i SpringLayout. Dintre acestea, SpringLayout,
GroupLayout i BoxLayout fac parte din Swing Layouts.
S ne reamintim modul n care funcioneaz Layout-urile AWT de baz.

2.1. Java AWT Layouts


Layout-ul default al containerului creat este BorderLayout, ceea ce nseamn c
ntreaga fereastr va fi mprit n cinci pri: nord, vest, est, sud i mijloc. Respectiv,
echivalentele acestora: Page start, Page end, Line start, Center i Line end.

Pentru a poziiona un anumit control ntr-o anumit parte din Layout, trebuie s-l
accentum n timpul utilizrii metodei add a containerului nsui, atunci cnd vom introduce
numele prii containerului ca al doilea parametru.
Pentru a umple toate prile containerului din imagine, putem utiliza codul urmtor:
import java.awt.*;
public class Main {
public static void main(String[] args) {
Frame f = new Frame();
Label l = new Label("Helo from top of the page");
Label l1 = new Label("Helo from center of the page");
Label l2 = new Label("Helo from bottom of the page");
Label l3 = new Label("left");
Label l4 = new Label("right");
f.add(l,BorderLayout.PAGE_START);
f.add(l1,BorderLayout.CENTER);
f.add(l2,BorderLayout.PAGE_END);
f.add(l3,BorderLayout.LINE_START);
f.add(l4,BorderLayout.LINE_END);
f.setSize(300, 300);
f.setVisible(true);
}
}
a) Border Layout este mai dificil, deoarece
controalele din fiecare parte sunt plasate unul
peste altul, ceea ce nseamn c putem avea
numai un control (sau container) vizibil ntro parte a Layout-ului.

b) FlowLayout expune toate controalele unul dup altul, orizontal, pn la captul


containerului, dup care trece pe un alt rnd, continund expunerea. Prin default, controalele
din acest Layout sunt expuse central, n mijloc, iar dac dorim un alt tip de centrare, trebuie
s-l menionm n constructorul FlowLayout.

Avnd n vedere c FlowLayout nu este layout-ul default al Frame-ului, trebuie s indicm


explicit c acesta este cel pe care dorim s-l utilizm (acest lucru se aplic tuturor Layouturilor):
...
LayoutManager layOut = new FlowLayout(FlowLayout.LEFT);
...
f.setLayout(layOut);
...
Cnd atribuim Layout-ul containerului, prin metoda setLayout, care accept obiectul
LayoutManager sub form de parametru, toate controalele adugate n container vor fi
poziionate n funcie de acest Layout:
import java.awt.*;
public class Main {
public static void main(String[] args) {
LayoutManager layOut = new FlowLayout(FlowLayout.LEFT);
Frame f = new Frame();
f.setLayout(layOut);
Button b = new Button("button 1");
Button b1 = new Button("button 2");
Button b2 = new Button("button 3");
f.add(b);
f.add(b1);
f.add(b2);
f.setSize(300, 300);
f.setVisible(true);
}
}
Urmtoarea ieire reprezint un exemplu:
c) GridLayout creaz un tabel n container, unde fiecare celul din tabel reprezint un
spaiu pentru control. Construcia tabelului (numrul de coloane i de rnduri) este creat n
constructorul obiectului GridLayout. De exemplu, constructorul pentru un tabel cu dou
rnduri i trei coloane va arta astfel:
LayoutManager layOut = new GridLayout(2, 3);
Dac numrul de controale depete capacitatea tabelului (exist ase celule n tabel),
una dintre dimensiunile tabelului va ctiga prioritate asupra celeilalte. De exemplu, dac
ncercm s punem 10 controale n tabelul 2x3, va fi respectat regula de 2 rnduri, dar va
crete numrul de coloane. Dac dorim s se respecte numrul de coloane n detrimentul
numrului de rnduri, trebuie s setm numrul de rnduri la 0:
LayoutManager layOut = new GridLayout(2, 3);
Urmtorul exemplu ilustreaz utilizarea GridLayout-ului (codul pentru adugarea
controalelor funcioneaz la fel ca n exemplul precedent, dar este optimizat pentru a
economisi spaiu):
import java.awt.*;
public class Main {
public static void main(String[] args) {
LayoutManager layOut = new GridLayout(3, 3);
Frame f = new Frame();
f.setLayout(layOut);

for(int i=0;i<10;i++)
f.add(new Button("Button "+ i));
f.setSize(300, 300);
f.setVisible(true);
}
}
Exemplul d urmtoarea ieire:

Putem
controla
respingerea
controalelor de marginile celulei. n acest caz,
vom introduce nc doi parametri n
constructor, respingerea orizontal i
vertical.
De exemplu:
LayoutManager layOut = new GridLayout(3, 3, 10,10);
d) CardLayout este un Layout oarecum mai exotic fa de precedentele. Poate s conin mai
multe containere, n timp ce numai unul va fi afiat la un moment dat. n acest mod, se obine
posibilitatea de a crea panouri.
Setarea CardLayout-ului i utilizarea sa sunt puin mai complicate fa de utilizarea
celorlalte Layout-uri.
Mai nti trebuie s crem un panou care le va conine pe celelalte panouri. Acest
panou va fi ntodeauna vizibil, iar Layout-ul su va fi CardLayout:
...
Panel mainPanel = new Panel();
CardLayout layOut = new CardLayout();
mainPanel.setLayout(layOut);
...
Dup crearea panoului principal, vom crea subpanourile sale. De exemplu, vom face
dou subpanouri care vor conine dou butoane:
...
Panel firstP = new Panel();
firstP.add(new Button("first panel button"));
Panel secondP = new Panel();
secondP.add(new Button("second panel button"));
...
Dup crearea subpanourilor, le vom aduga n panoul principal, moment n care le
vom atribui un nume logic, respectiv constraint, prin care vor fi identificate n lista panoului:
...
mainPanel.add(firstP,"First");
mainPanel.add(secondP,"Second");
...
n cele din urm, vom activa panoul dorit, prin metoda show a clasei CardLayout, i
vom aduga panoul principal n aplicaia principal:
...
layOut.show(mainPanel, "Second");
f.add(mainPanel);
...

Metoda show a clasei CardLayout accept doi parametri: numele panoului printe
(n cazul nostru, acesta este mainPanel) i numele panoului pe care dorim s-l afim. Pentru
numele panoului pe care dorim s-l afim, vom introduce numele su logic, adic constraint.
Pentru a schimba panoul existent, vom utiliza de asemenea metoda show.
Urmtorul exemplu ilustreaz schimbarea panoului curent prin activarea butonului:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main {
static CardLayout layOut;
static Panel mainPanel;
static Frame f;
public
static
void
main(String[]
args)
throws
InterruptedException {
f = new Frame();
mainPanel = new Panel();
layOut = new CardLayout();
mainPanel.setLayout(layOut);
Panel firstP = new Panel();
Panel secondP = new Panel();
Button b = new Button("first panel button");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layOut.show(mainPanel, "Second");
}
});
Button b1 = new Button("second panel button");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layOut.show(mainPanel, "First");
}
});
firstP.add(b);
secondP.add(b1);
mainPanel.add(firstP,"First");
mainPanel.add(secondP,"Second");
f.add(mainPanel);
f.setSize(300, 300);
f.setVisible(true);
}
}
Ieirea acestui exemplu este urmtoarea:

2.2. Java Swing Layouts


Swing aduce cu sine noi clase LayoutManager: GroupLayout, BoxLayout. Si
SpringLayout.
B) GroupLayout este LayoutManager-ul default al designerului JDeveloper (GUI Builder).
Acest layout implic o fereastr mprit n grupuri i chiar dac mediul l utilizeaz, acesta
nu este foarte simplu de utilizat manual.
8

GroupLayout implic dou direcii (orizontal i vertical) i dou tipuri de setri ale
controalelor (secvenial i paralel).

Pentru a seta un anumit control, trebuie s crem un grup de un anumit tip. Dac ne
uitm la imagine ca la un grup orizontal, putem spune c grupul este alctuit din dou
butoane. 1: Hello a i 2: Hello b. Acest grup se mut secvenial, de la stnga la dreapta.
Dac ne utitm la imagine vertical, de sus n jos, butoanele nu vor fi aranjate secvenial, ci
paralel, deoarece sunt plasate unul lng altul pe acelai plan. Acum grupul este: 1: Hello a i
1: Hello b.
Atunci cnd combinm aceste dou zone, rezultatul este c fereastra conine un grup
orizontal, secvenial, de dou butoane i un grup vertical, paralel, de dou butoane. Cnd acest
lucru este tradus n Java, rezultatul este codul urmtor:
GroupLayout layout = new GroupLayout(this.getContentPane());
this.setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
JButton a = new JButton("Hello a");
JButton b = new JButton("Hello b");
layout.setHorizontalGroup(
layout.createSequentialGroup()
.addComponent(a).addComponent(b)
);
layout.setVerticalGroup(
layout.createParallelGroup()
.addComponent(a).addComponent(b)
);
Observm c aceleai controale apar att n grupul orizontal, ct i n cel vertical.
Aceste controale trebuie s se suprapun pe poziiile or orizontale i verticale, pentru ca
Layout-ul c fie creat n mod corespunztor. Aceasta nseamn c controalele nu pot fi create
dinamic, motiv pentru care acest Layout nu este convenabil pentru utilizare n afara
platformei.
Metodele setAutoCreateGaps i setAutoCreateContainerGaps definesc n mod
automat spaiul dintre controalele din cadrul grupului.
C) BoxLayout red controalele unul dup altul, pe o anumit ax:

...
this.setLayout(new BoxLayout(this.getContentPane(),
BoxLayout.Y_AXIS));
for(int i=0;i<10;i++)
this.getContentPane().add(new JButton("Hello "+i));
...
C) SpringLayout ofer setarea constrngerilor (metoda
putConstraint), astfel nct fiecare control s fie plasat
ntr-o anumit locaie, respectnd regulile unei anumite
constrngeri. n imaginea viitoare, butonul este
restricionat la 100 de pixeli spre vest i 150 de pixeli
spre nord:

O astfel de abordare ne permite s poziionm controlul n oricare loc din fereastr.


De exemplu:
...
SpringLayout layout = new SpringLayout();
this.getContentPane().setLayout(layout);
JButton a = new JButton("Hello a");
this.getContentPane().add(a);
layout.putConstraint(SpringLayout.WEST, a,100,
SpringLayout.WEST, this.getContentPane());
layout.putConstraint(SpringLayout.NORTH, a,150,
SpringLayout.NORTH, this.getContentPane());
...
Clasa Border. Clasa Border este clasa prin care este reprezentat proprietatea border a
majoritii componentelor Swing. Proprietatea nsi este setat prin metoda setBorder, iar
tipul este instaniat prin clasa BorderFactory:
JButton btn = new JButton("Hello");
Border b = BorderFactory.createLineBorder(Color.GREEN,5);
btn.setBorder(b);
Proprietatea border nu trebuie s fie setat dintr-o instan denumit; aceasta poate fi setat i
anonim, dar n acest fel nu ar avea niciun sens, deoarece cadrul setat nu poate fi atribuit altor
componente:
btn.setBorder(BorderFactory.createLineBorder(Color.GREEN,5));
Clasa BorderFactory conine o mulime de metode pentru crearea diferitelor cadre stilizate.
n funcie de tipul de cadru, fiecare metod are un set corespunztor de parametri:
btn.setBorder(BorderFactory.createLineBorder(Color.yellow,
3));
btn.setBorder(BorderFactory.createBevelBorder(1));
btn.setBorder(BorderFactory.createEtchedBorder(EtchedBord
er.RAISED));

10

btn.setBorder(BorderFactory.createMatteBorder(15, 5, 15, 5,
Color.yellow));
btn.setBorder(BorderFactory.createTitledBorder("My
title"));

border

Proprietatea border poate fi setat i prin GUI Builder. Trebuie s selectm tipul dorit
al cadrului i s-l tragem n control (sau, pur i simplu, s dm un clic cu tasta stng a
mouse-ului pe cadru i nc o dat pe controlul int):
Pentru a modifica setrile cadrului, n proprietile controlului (Properties), vom
selecta opiunea Border:

Aceasta activeaz instrumentul Border customizer cu care putem modifica


proprietile i chiar s nlocuim cadrul existent cu altul:

III. Exerciiu/Tem
Problem:
Trebuie s facem o aplicaie Java puzzle. Aplicaia va
fi alctuit din 12 butoane distribuite pe controlul
JFrame, utiliznd GridLayout. Unul dintre butoane va fi
ntodeauna invizibil i fiecare buton care va fi apsat va
fi mutat n locul celui invizibil, n timp ce butonul
invizibil i va lua locul. Dac butonul activat nu este
plasat lng butonul invizibil, nlocuirea butonului ar
trebui s fie dezactivat.
Soluie:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JButton;
public class Main {
static JButton invisible;
static void switchButtons(JButton clickedButton)
{
if(
invisible.getLocation().x < (clickedButton.getLocation().x clickedButton.getSize().width) ||
invisible.getLocation().x > (clickedButton.getLocation().x +
clickedButton.getSize().width) ||
invisible.getLocation().y < (clickedButton.getLocation().y clickedButton.getSize().height) ||
11

invisible.getLocation().y > (clickedButton.getLocation().y +


clickedButton.getSize().height) ||
(invisible.getLocation().y !=clickedButton.getLocation().y &&
invisible.getLocation().x !=clickedButton.getLocation().x)
)
return;
Point tmpLoc = clickedButton.getLocation();
clickedButton.setLocation(invisible.getLocation());
invisible.setLocation(tmpLoc);
}
public static void main(String[] args) {
LayoutManager layOut = new GridLayout(3, 3);
Frame f = new Frame();
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setLayout(layOut);
JButton btn = new JButton();
for(int i=1;i<13;i++)
{
btn = new JButton(String.valueOf(i));
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
switchButtons((JButton)e.getSource());
}});
f.add(btn);
}
btn.setVisible(false);
invisible = btn;
f.setSize(300, 300);
f.setVisible(true);
}
}
n scopul exersrii independente, adugai n exemplul anterior implementarea pentru
poziionarea butoanelor (numerelor) la ntmplare, precum i controlul pentru nceputul i
finalul jocului (finalul va avea loc atunci cnd toate numerele sunt aranjate n mod
corespunztor de la 1 la 11.

III. Bibliografie
http://docs.oracle.com/cd/E24382_01/user.1112/e17455/java_swing.htm
http://docs.oracle.com/middleware/1212/jdev/OJDUG/java_swing.htm

12

04. Distribuirea componentelor ntr-un container

1. Cum se numete proprietatea prin care este reprezentat cadrul din control?
border
edge
stroke
outline
2. Care swing layout poziioneaz controalele unul dup cellalt, de-a lungul unei anumite
axe?
FlowLayout
BoxLayout
SpringLayout
GroupLayout
3. Dac utilizm limitatori pentru a poziiona un control pe layout, despre ce tip de swing
layout este vorba?
BoxLayout
GroupLayout
SpringLayout
FlowLayout
4. Cum se numete instrumentul care ofer manipularea grafic a cadrelor?
Border wizard
Border customizer
Border modifier
Border creator
5. Care este numele clasei care conine metodele pentru crearea diferitelor obiecte Border?
BorderCreator
Borders
BorderFactory
Border
6. Care metod seteaz proprietatea border a controlului?
putBorder
setBorder
addBorder
border
7. Cnd vorbim despre Group Layout-ul vertical, avem urmtoarele dou tipuri de poziionare
a controalelor:
secvenial i paralel
orizontal i vertical
nord i sud
est i vest

13

S-ar putea să vă placă și