Obsah
API http://java.sun.com/javase/6/docs/api/javax/swing/JPanel.html
nejpoužívanější kontainer v JFC-Swing
někdy se používá opravdu jako kontejner, tj. pro optické seskupení několik jiných komponent
většinou se používá pro řízení toho, jak mají být komponenty rozmístěny
při návrhu GUI typicky použijete až desítky instancí JPanel
screenshot z http://java.sun.com/docs/books/tutorial/uiswing/components/panel.html (btw, doporučená četba)
při ladění GUI je užitečné nastavit pozadí panelu na nějakou barvu (ale jen při ladění)
používané metody jsou v podstatě jen:
add(parametry)
remove(parameter)
setLayout(parametr)
doporučená četba:
za umístění jednotlivých komponent v kontejnerové komponentě zodpovídá layout manager
objekt třídy java.awt.LayoutManager
resp.
některé ze zděděných tříd
ze jména balíčku je vidět, že to je jedna z oblastí kde Swing používá dědictví ze staršího AWT
každý kontejner má svůj vlastní implicitní layout manager, ale lze jej snadno vyměnit za jiný
typické použití jiného manageru je např.:
objektKontejneru.setLayout(new
FlowLayout());
každý layout manager má jiné možnosti, k dispozici jsou např.:
dva běžné – FlowLayout
a
GridLayout
speciální – BorderLayout
velmi sofistikovaný – GridBagLayout
téměř nikdy nevoláme jejich metody – stačí manager vytvořit
pomocí konstruktoru a použít metodu add()
pro umístění
komponent
v krajním případě lze použití layout managerů vypnout a rozmísťovat komponenty na absolutní pozice (souřadnice)
každý kontejner má svůj implicitní layout manager:
JPanel
– FlowLayout
JFrame
, JDialog
–
BorderLayout
vyhovuje-li implicitní layout manager, nemusíme dělat vůbec nic
http://java.sun.com/docs/books/tutorial/uiswing/layout/flow.html
vkládané komponenty rozmísťuje v pořadí vložení do řádky a nemění jejich velikosti implicitně centrovaně s pětibodovou mezerou mezi nimi
nevejdou-li se na řádku, pokračuje na další řádce
výška řádky je odvozena od výšky nejvyšší komponenty
při použití pack()
dostaneme jen jednu řádku
komponent -- pack()
nastaví velikost okna "tak akorát"
podle hodnot vrácených po volání getPreferedSize()
komponent umístěných k okně
požadujeme-li více řádek, musíme použít
setSize()
u kontejneru
vkládá komponenty v pořadí vložení do předdefinované mřížky
na další řádku přechází, když vyplní všechny sloupce na stávající řádce
např. GridLayout experimentLayout = new
GridLayout(2,3);
horizontální i vertikální velikosti komponent nastavuje podle velikosti největší komponenty v řádku/sloupci pro všechny řádky a sloupce jednotně
vyplní celou plochu kontejneru (vlevo s
setHGap(5)
a setVgap(10)
)
http://java.sun.com/docs/books/tutorial/uiswing/layout/border.html
může umístit maximálně pět komponent
umístění nezáleží na pořadí vložení – je přesně specifikováno „světovou stranou“
lze použít konstanty NORTH
,
SOUTH
, WEST
,
EAST
,
CENTER
vkládané komponenty zvětšuje podle následujícího algoritmu:
severní a jižní – roztáhne na maximální šířku, ale ponechá výšku
západní a východní – roztáhne do maximální výšky, ale ponechá jejich šířku
středová – vyplní všechen zbylý prostor
není-li v některé „světové straně“ umístěna komponenta, ostatní se do tohoto směru roztáhnou
je matoucí různé použití metody add()
– existují
až čtyři funkční možnosti
this.add(new Button("Sever"), BorderLayout.NORTH); this.add(new Button("Jih"), "South"); this.add(BorderLayout.WEST, new Button("Zapad")); this.add("East", new Button("Vychod"));
zásadně používat jen první z nich
http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbag.html
nejvíce sofistikovaný (hodně možností), ale prakticky nejužívanější, protože dává většinou nejlepší výsledky
spolupracují třídy GridBagLayout
a
GridBagConstraints
využívá strukturu mřížky, každá komponenta může obsadit více řádek a/nebo sloupců
každé komponentě lze individuálně stanovit pozici, roztažitelnost, velikost, okraje a umístění
dodržuje-li se v kódu pořádek, je použití přímočaré, ale zdlouhavé
public class MujGridBagLayout extends JFrame { private GridBagLayout gbl; private GridBagConstraints gbc; private JPanel vnitrekPN; private static final int NON=GridBagConstraints.NONE; . . . MujGridBagLayout() { this.setTitle(getClass().getName()); this.getContentPane().add(vytvorVnitrek()); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.pack(); this.setVisible(true); } private void nastav(Component c, int x, int y, int s, int v, double rs, double rv, int vyp, int k) { gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = s; gbc.gridheight = v; gbc.weightx = rs; gbc.weighty = rv; gbc.fill = vyp; gbc.anchor = k; gbl.setConstraints(c, gbc); vnitrekPN.add(c); } Container vytvorVnitrek() { JButton btn; vnitrekPN = new JPanel(); gbl = new GridBagLayout(); vnitrekPN.setLayout(gbl); gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 5, 5, 5); btn = new JButton("Tl. 1"); nastav(btn, 0, 0, 1, 1, 0.0, 0.0, NON, WES); btn = new JButton("Tlač. 2"); nastav(btn, 1, 0, 1, 1, 0.0, 0.0, NON, CEN); btn = new JButton("Tlačítko 3"); nastav(btn, 2, 0, 1, 1, 0.0, 0.0, NON, EAS); btn = new JButton("Tlač. 4"); nastav(btn, 0, 1, 2, 1, 1.0, 0.0, HOR, CEN); btn = new JButton("Tlačítko 5"); nastav(btn, 2, 1, 1, 2, 1.0, 1.0, BOT, CEN); btn = new JButton("Tlačítko 6"); nastav(btn, 0, 2, 1, 1, 0.0, 0.0, NON, EAS); btn = new JButton("T. 7"); nastav(btn, 1, 2, 1, 1, 0.0, 0.0, NON, WES); return vnitrekPN; }
nejedná se přímo o použití grafiky, ale o umístění obrázku na
nejčastěji JButton
výhodou je, že všechna známá práce s "buttonem" zůstává zcela stejná
používáme ikony, tj. objekty s obrázky pevné velikosti
splňující rozhraní javax.swing.Icon
pro zjednodušení práce se používá třída
javax.swing.ImageIcon
, která umí vykreslit obrázky ve
formátech GIF, JPEG a PNG
ikony může doprovázet současně zobrazený text, ale toto se používá zřídkakdy
většinou je ikona doprovázena bublinkovou nápovědou
javax.swing.JToolTip
, což je něco jiného než text
na tlačítku (viz dále)
import java.net.*; import java.awt.*; import javax.swing.*; public class NacteniIkony { public static void main(String[] args) throws Exception { JFrame oknoF = new JFrame("NacteniIkony"); oknoF.setLayout(new FlowLayout()); ImageIcon krizekIK = new ImageIcon("krizek.jpg"); JButton krizekBT = new JButton("krizek", krizekIK); ImageIcon koleckoIK = new ImageIcon("ikony/kolecko.jpg"); JButton koleckoBT = new JButton(koleckoIK); koleckoBT.setMargin(new Insets(0,0,0,0)); URL trojuhURL = NacteniIkony.class.getResource("ikony/trojuh.jpg"); ImageIcon trojuhIK = new ImageIcon(trojuhURL); JButton trojuhBT = new JButton(trojuhIK); trojuhBT.setToolTipText("trojúhelník"); oknoF.add(krizekBT); oknoF.add(koleckoBT); oknoF.add(trojuhBT); oknoF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); oknoF.setSize(320, 90); oknoF.setVisible(true); } }
pokud bude program spouštěn z .class
souboru, lze obrázek natáhnout
ImageIcon krizekIK = new ImageIcon("krizek.jpg");
(je-li ve stejném adresáři jako .class
soubor)
jako oddělovač adresářů se používá /
ImageIcon koleckoIK = new
ImageIcon("ikony/kolecko.jpg");
u takto natahovaných souborů nezáleží na velikosti písmen ve
jménu krizek.jpg
je stejné jako
krizek.JPG
pro spuštění z .jar
souboru toto
jednoduché natažení nefunguje a je třeba použít instanci
java.net.URL
URL trojuhURL =
NacteniIkony.class.getResource("ikony/trojuh.jpg");
v případě, že URL získáváme v instanční metodě, lze použít
URL trojuhURL =
getClass().getResource("ikony/trojuh.jpg");
při použití URL záleží na velikosti písmen ve jménu souboru
krizek.jpg
je různé od
krizek.JPG
u JButtonu
se ještě přidají k obrázku okraje,
kterých se lze zbavit:
koleckoBT.setMargin(new Insets(0,0,0,0));
popis tlačítka je něco jiného než tooltip (bublinková nápověda)
JButton krizekBT = new JButton("krizek", krizekIK); trojuhBT.setToolTipText("trojúhelník");
popisu ikony (současně s obrázkem) se snažíme zbavit – viz dále
pro soubory obrázků ikon je lepší použít formát GIF než JPEG, zejména kreslíme-li je sami
použijeme komponentu JToolBar
import java.net.*; import java.awt.*; import javax.swing.*; public class ToolBarVytvoreni { public ToolBarVytvoreni() { JFrame oknoF = new JFrame("ToolBarVytvoreni"); oknoF.setLayout(new BorderLayout()); oknoF.add(vytvorToolBar(), BorderLayout.PAGE_START); oknoF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); oknoF.pack(); oknoF.setVisible(true); } ImageIcon nactiObrazekIkony(String jmeno) { URLClassLoader urlLoader = (URLClassLoader) this.getClass().getClassLoader(); URL ikonaURL = urlLoader.findResource("ikony/" + jmeno + ".gif"); ImageIcon ikonaIK = new ImageIcon(ikonaURL); return ikonaIK; } JButton vytvorTlacitkoProToolbar(String jmenoObrazkuIkony, String toolTip) { JButton tlac = new JButton(nactiObrazekIkony(jmenoObrazkuIkony)); if (tlac.getIcon() != null) { tlac.setText(""); // je-li obrazek, neni treba popis } tlac.setMargin(new Insets(0,0,0,0)); tlac.setToolTipText(toolTip); return tlac; } JToolBar vytvorToolBar() { JToolBar hlavniTB = new JToolBar("Jméno ToolBaru"); JButton tl = vytvorTlacitkoProToolbar("krizek", "křížek - tool tip"); hlavniTB.add(tl); hlavniTB.add(vytvorTlacitkoProToolbar("kolecko", "kolečko - tool tip")); hlavniTB.addSeparator(new Dimension(100, 20)); // rozměr "natvrdo" hlavniTB.add(vytvorTlacitkoProToolbar("trojuh", "trojúhelník - tool tip")); hlavniTB.setFloatable(false); hlavniTB.setRollover(true); return hlavniTB; } public static void main(String[] args) throws Exception { new ToolBarVytvoreni(); } }
aby JToolBar
správně pracoval, je vhodné použít
jako layout manager hlavního okna BorderLayout
a
JToolBar
umístit nahoru
oknoF.add(vytvorToolBar(),
BorderLayout.PAGE_START);
pojmenování tool baru není nutné, ale pokud bude přemístitelný (floatable), je to velmi vhodné
JToolBar hlavniTB = new JToolBar("Jméno
ToolBaru");
jednotlivá tlačítka (ikony) mísťujeme nejjednodušeji v pořadí výskytu
hlavniTB.add(tl);
mezi ikony lze umístit oddělovací mezeru, jejíž rozměr lze volit
hlavniTB.addSeparator();
nebo
hlavniTB.addSeparator(new Dimension(100,
20));
tool bar je implicitně nastaven jako přemístitelný (floatable), což znamená možnost přesunout jej dynamicky doleva, doprava nebo dolů v hlavním okénku
další možnost je „vytáhnout“ jej zcela mimo hlavní okénko
pak bude mít nově vzniklé okénko jméno, které jsme použili
v konstruktoru JToolBar
zpět do hlavního okénka se dostane zavřením
vlastnost přemístitelnosti lze zakázat (většinou rozumná volba)
hlavniTB.setFloatable(false);
velmi užitečná vlastnost se dá zapnout pomocí
hlavniTB.setRollover(true);
pak by byla orámovaná pouze ikona s fokusem
bohužel: „The implementation of a look and feel may choose to ignore this property.“