2. GUI . Správcovia
rozmiestnenia. Ďalšie komponenty
Cieľom kapitoly je predovšetkým ukázať, ako pracujú
správcovia rozmiestnenia pri rozmiestňovaní prvkov na komponentu. Zoznámime sa
aj s niektorými novými komponentami.
Obsah celej tejto kapitoly sa bude tak trochu podobať na katalóg. Najprv si predstavíme niektoré grafické prvky v práci. Medzi nimi aj pár nových.
Hlavnou náplňou kapitoly je ukázať, akým spôsobom sa
pracuje s jednotlivými správcami rozmiestnenia.
V nasledujúcom kóde uvidíme, ako jednoducho sa
definuje textové pole s posuvnou lištou.
Takisto si ukážeme, ako možno formátovať text pomocou HTML. Ukážeme si
to na príklade tlačítka. Ľubovoľný ovládací prvok, ktorý dokáže prevziať text,
dokáže takisto prevziať text, formátovaný v jazyku HTML. Takýto text musí
začínať značkou <HTML> . Môžu sa v ňom používať všetky bežné
značky tohto jazyka. Všimnite si, že nie je vždy nutné uvádzať aj zakončovacie
značky.
Kód
GR2.1
//program
vypíše zadaný počet riadkov textu
//
prvky:
//
popiska, textové políčko, tlačítko s HTML textom
//
Textové pole s posuvnou lištou
//
pouzitie HTML
import
javax.swing.*;
import
java.awt.*;
import java.awt.event.*;
class Daj{
public
String vyznanie(String pocetRiadkov){
int
riadky = 0;
String
zaklad = " milujem ta viac a viac";
String riadok = zaklad;
String
vystup = "Chyba v texte. \n Zadajte cislo prosim. ";
try{
riadky = Integer.parseInt(pocetRiadkov);
vystup = zaklad;
for(int i = 1; i < riadky; i++) {
riadok+= " a viac";
zaklad = vystup;
vystup+=
"\n " +riadok;
}//EOFor
}
catch(NumberFormatException
e){
vystup+= " \n \" " + pocetRiadkov + "\" nie je cislo." ;
}
finally{
return
vystup;
}
}//EOMethod
}//EOClass
public
class Prvky {
private JFrame ram = new
JFrame("Invertovanie");
private JLabel pocRiad = new
JLabel("Udaj pocet riadkov:");
private JTextField policko = new JTextField(4);
private JButton gombik = new
JButton("<HTML> <BODY BGCOLOR =yellow> SPUSTI ");
private JTextArea pole = new
JTextArea(8,20);
private Daj daj = new Daj();
class
PosluchacG implements ActionListener {
public
void actionPerformed(ActionEvent e) {
String
text = policko.getText();
text =
daj.vyznanie(text);
pole.setText(text);
}
}
PosluchacG ucho = new
PosluchacG();
public
void init(){
Container
cp = ram.getContentPane();
cp.setLayout(new FlowLayout());
cp.add(pocRiad);
cp.add(policko);
cp.add(gombik);
//
prida JTextArea "pole" uz zabalene tak,
//
ze ma pridane posuvne listy
cp.add(new
JScrollPane(pole));
//mohli
by sme pridat posluchaca az tu
gombik.addActionListener(ucho);
ram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ram.setSize(300,250);
ram.setVisible(true);
}
public
static void main(String[] args){
Prvky
prvy = new Prvky();
prvy.init();
}//EOMain
}//EOClass
Triedy JApplet, JFrame JWindow, a JDialog vedia
vytvoriť objekt typu Container pomocou
metódy getContentPane( ). Tento objekt môže obsahovať
a zobrazovať jednotlivé komponenty. (Najprv ich však naň musíme uložiť).
Trieda Container má tiež k dispozícii metódu setLayout( ). Tá slúži na to, aby
sme si mohli zvoliť vhodného správcu rozmiestnenia.
Niektoré triedy, ako napríklad JPanel, dedič triedy
Container, umožňujú ukladať komponenty priamo. Ak chceme pri ukladaní na ne
použiť správcu rozmiestnenia, zavoláme metódu setLayout() priamo z nich.
Napríklad takto:
JPanel jp =
new JPanel();
jp.setLayout(new BorderLayout());
V nasledujúcich kódoch si predvedieme ukladanie
jednoduchých komponent. V každom príklade použijeme iného správcu
rozmiestnenia. Zostaneme pri tejto „grafickej“ časti kódovania. Nebudeme
definovať žiadnych poslucháčov a teda ani zachytávať žiadne udalosti.
Použitie správcu typu FlowLayout sme už videli v kóde Gr1.2. FlowLayout jednoducho ukladá prvky zľava doprava až kým sa horná časť formulára nezaplní. Potom začne ukladať prvky tým istým spôsobom na nasledujúci riadok. Pozrime sa príklad ukladania tlačítok pomocou tohto správcu. Základný kontajner s 25 tlačítkami sa zobrazí vo väčšom rozmere, po piatich sekundách sa zmení na menší. Tým sa zmení aj rozmiestnenie tlačítok.
import javax.swing.*;
import java.awt.*;
// import javax.swing.*;
public class SkusFlowLayout extends JFrame{
public void spusti(int sirka, int vyska){
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
// umiestnime na kontajner 25 tlacitiek
for(int i = 1; i < 26; i++){
cp.add((new JButton(" " + String.valueOf(i) + " ")));
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(sirka, vyska);
this.setVisible(true);
}
public static void main(String[] args){
SkusFlowLayout prvy = new SkusFlowLayout();
prvy.spusti(600,600);
// cakaj 5 sekund
long time = System.currentTimeMillis() + 5000;
while(System.currentTimeMillis() < time) ;
prvy.spusti(100,300);
}//EOMain
}//EOClass
Správca rozmiestnenia GridLayout
Tento správca umožňuje vytvoriť tabuľku komponent. Jeden z jeho konštruktorov umožňuje určiť počet riadkov a stĺpcov. Pozmeňme kód z predchádzajúceho príkladu na tento:
import javax.swing.*;
import java.awt.*;
public class SkusGridLayout extends JFrame {
public void spusti(int sirka, int vyska){
Container cp = getContentPane();
cp.setLayout(new GridLayout(9,3));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
V kóde „Gr2.4 “ bude našou základnou
triedou JApplet. Zvolili sme ho
z toho dôvodu, že má ako layout manažéra defaultne nastavený práve BorderLayout. Na JApplet budeme
ukladať komponenty – inštancie triedy JPanel.
import javax.swing.*;
import java.awt.*;
// applet nechceme spustat na sieti
// metodu init() mozeme vynechat
public class
SkusBorderLayout extends
JApplet{
public
void spusti(int sirka, int vyska){
Container
cp = getContentPane();
//
JApplet ma defaultne nastaveny BorderLyout
// cp.setLayout(new BorderLayout()); // netreba
cp.add(BorderLayout.NORTH,(new JPanel()).add(new
JLabel("Sever")));
cp.add(BorderLayout.SOUTH,(new JPanel()).add(new
JLabel("Juh")));
JPanel
jp = new JPanel();
jp.add(new JLabel("Vychodny "));
jp.add(new JLabel("blok "));
cp.add(BorderLayout.EAST,jp);
cp.add(BorderLayout.WEST,(new JPanel()).add(new
JLabel("Zapad")));
cp.add(BorderLayout.CENTER,(new JPanel()).add(new JLabel(" STRED")));
//
cp.add((new JPanel()).add(new JLabel(" TIEZ STRED"))); //umiestni
tiez do stredu
JFrame frame = new JFrame("Skusam BorderLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(this);
frame.setSize(sirka, vyska);
frame.setVisible(true);
}
public
static void main(String[] args){
SkusBorderLayout sbl = new SkusBorderLayout();
sbl.spusti(400,100);
}//EOMAin
}//EOClass
Správca rozmiestnenia BoxLayout
Táto trieda umožňuje riadiť rozmiestňovanie komponent jednak vo zvislom, jednak vo vodorovnom smere. Umožňuje tiež určiť medzery medzi jednotlivými prvkami. Ukážme si použitie tohto správcu na dvoch jednoduchých príkladoch:
import javax.swing.*;
import java.awt.*;
public class SkusBoxLayout {
JPanel vodorovny = new JPanel();
JPanel zvisly = new JPanel();
JFrame ram = new JFrame("Testing BoxLayout");
public SkusBoxLayout(){
//
vodorovny.setLayout(new BoxLayout(vodorovny, BoxLayout.X_AXIS) );
for(int i = 1; i < 7; i++){
vodorovny.add(new Button(" " + i + " "));
}
zvisly.setLayout(new BoxLayout(zvisly, BoxLayout.Y_AXIS) );
for(int i = 1; i < 7; i++){
zvisly.add(new Button(" " + i + " "));
}
Container cp = ram.getContentPane();
cp.setLayout(new GridLayout(2,1));
cp.add(vodorovny);
cp.add(zvisly);
ram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void zobraz(int sirka, int vyska){
ram.setSize(sirka,vyska);
ram.setVisible(true);
}
public static void main(String[] args){
SkusBoxLayout skus = new SkusBoxLayout();
skus.zobraz(400,400);
}//EOMain
}//EOClass
Všimnime si riadok:
vodorovny.setLayout(new BoxLayout(vodorovny, BoxLayout.X_AXIS) );
Vidíme, že BoxLayout, na rozdiel od iných správcov, potrebuje mať v konštruktore ako prvý argument kontajner, ktorý bude spravovať.
V kóde zároveň vidíme možnosť kombinovania viacerých správcov rozmiestnenia.
V predošlom kóde pôsobí trochu kostrbato vytvorenie panelu príkazom
JPanel vodorovny = new JPanel();
a pridanie správcu príkazom
vodorovny.setLayout(new BoxLayout(vodorovny, BoxLayout.X_AXIS) );
Rovnaký efekt sa dá dosiahnuť jedným príkazom vďaka triede Box. Tá má statickú metódu, ktorá umožní vytvoriť kontajner typu Box, ktorý má už priamo, defaultne nastavený vertikálny alebo horizontálny spôsob ukladania pomocou správcu typu BoxLayout. Princíp ľahko pochopíme po miernom prepísaní predchádzajúceho kódu:
import javax.swing.*;
import java.awt.*;
public class LepsiBoxLayout {
Box vodorovny = Box.createHorizontalBox();
Box zvisly = Box.createVerticalBox();
JFrame ram = new JFrame("Testing BoxLayout");
public LepsiBoxLayout(){
//
//vodorovny.setLayout(new BoxLayout(vodorovny, BoxLayout.X_AXIS) );
for(int i = 1; i < 7; i++){
vodorovny.add(new Button(" " + i + " "));
}
for(int i = 1; i < 7; i++){
zvisly.add(new Button(" " + i + " "));
}
Container cp = ram.getContentPane();
cp.setLayout(new GridLayout(2,1));
cp.add(vodorovny);
cp.add(zvisly);
ram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void zobraz(int sirka, int vyska){
ram.setSize(sirka,vyska);
ram.setVisible(true);
}
public static void main(String[] args){
LepsiBoxLayout skus = new LepsiBoxLayout();
skus.zobraz(400,400);
}//EOMain
}//EOClass
Nasledujúci príklad ukazuje použitie „rozpier“ a „tmelu“. Rozpery (Struts) sú medzery-oddeľovače medzi komponentami, ktorých veľkosť je presne určená. Konkrétne je určená v pixeloch. Oddeľovače typu Tmel (Glue) oddelia od seba komponenty tak ďaleko, ako je to len možné.
import javax.swing.*;
import java.awt.*;
public class GlueAndStruts {
Box vodorovny = Box.createHorizontalBox();
Box zvisly = Box.createVerticalBox();
JFrame ram = new JFrame("Testing BoxLayout");
public GlueAndStruts(){
//
//vodorovny.setLayout(new BoxLayout(vodorovny, BoxLayout.X_AXIS) );
for(int i = 1; i < 5; i++){
vodorovny.add(new JLabel(" " + i + " "));
vodorovny.add(Box.createHorizontalGlue());
}
vodorovny.add(new JLabel(" a "));
vodorovny.add(Box.createHorizontalStrut(10));
vodorovny.add(new JLabel(" b "));
for(int i = 1; i < 4; i++){
zvisly.add(new Button(" " + i + " "));
zvisly.add(Box.createVerticalStrut(2*i));
}
zvisly.add(new Button(" a "));
zvisly.add(Box.createVerticalGlue());
zvisly.add(new Button(" b "));
Container cp = ram.getContentPane();
cp.setLayout(new GridLayout(2,1));
cp.add(vodorovny);
cp.add(zvisly);
ram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void zobraz(int sirka, int vyska){
ram.setSize(sirka,vyska);
ram.setVisible(true);
}
public static void main(String[] args){
GlueAndStruts skus = new GlueAndStruts();
skus.zobraz(400,550);
}//EOMain
}//EOClass
Cvičenia
Cvičenie C13.1
V kóde Gr2.2 zmeňte iba jednu vec: naukladajte prvky na komponentu nie pomocou správcu typu FlowLayout, ale pomocou správcu BoxLayout. Sledujte, ako sa teraz zmení vzhľad okna, keď bude meniť svoju veľkosť.
Cvičenie C13.2
Uložte, podobne ako v kóde
Gr2.3 viacero tlačítok na komponentu pomocou správcu GridLayout. Tentokrát ale
použite jeho konštruktor tvaru
GridLayout(int rows, int cols, int hgap, int vgap)
ktorý určí aj veľkosť horizontálnych a verikálnych medzier medzi pridávanými prvkami.
Cvičenie C13.3
Pozrite si dokumentáciu k triede GridBagLayout. Spustite kód, ktorý je v dokumentácii uvedený ako príklad. Ak treba, upravte ho tak, aby používal JFrame miesto Frame a upravte príslušne pridávanie prvkov na komponentu. Snažte sa kódu porozumieť. Pridajte potom na komponentu pod staré prvky nový riadok prvkov, podľa svojich vlastných predstáv.
© Ivan Kupka
Vaše komentáre:
kupka@fmph.uniba.sk