-
1
Distribuirea componentelor ntr-un container (Layout).
Clasele JFrame
Nu spune niciodat nu se poate, ci incepe cu s vedem. Nicolae
Iorga
Obiective: 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.
Cuprins: 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:
-
2
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:
-
3
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.
-
4
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.
-
5
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 ntr-
o 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.
-
6
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 Layout-urilor):
... 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);
-
7
for(int i=0;i
-
8
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.
-
9
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:
-
10
... this.setLayout(new BoxLayout(this.getContentPane(),
BoxLayout.Y_AXIS));
for(int i=0;i
-
11
btn.setBorder(BorderFactory.createMatteBorder(15, 5, 15, 5,
Color.yellow));
btn.setBorder(BorderFactory.createTitledBorder("My border
title"));
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) ||
-
12
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
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