|
||||||||||||||||||||||||||||||||||||||||||||||||
Menu
Distributions (131)
Software (10844)
|
Java (26) - tvorba GUIPři návrhu a implementaci grafického uživatelského rozhraní se lze vydat
dvěma hlavními cestami: buď tvořit ručně (přímým psaním kódu), nebo využít
grafické návrhové prostředí. Na obě se nyní podíváme, samozřejmě i včetně
kombinace obou přístupů. Při tom se dostanou ke slovu některé více či méně
zajímavé objektové třídy.
Okna, dialogy, rámyPrvky grafického rozhraní obvykle neplavou "ve vzduchu" (tedy jen tak na ploše obrazovky), i když to v některých případech bývá. Mnohem častěji je umísťujeme do různých oken. Před návrhem GUI nějaké aplikace se vyplatí dobře znát vlastnosti základních druhů oken, se kterými se ve frameworku Swing pracuje. Okno
Základním prvkem je "obyčejné" okno, reprezentované třídou Každé okno obsahuje určité plochy, které mají svůj význam pro fungování okna a s každou z nich se pracuje specifickým způsobem:
Zdaleka nejčastěji pracujeme s obsahovou plochou. Buď použijeme tu, která
je v okně již obsažena (ale pak předem neznáme její vlastnosti, resp. ani
třídu), nebo nastavíme komponentu vlastní. Vhodnými kandidáty bývají třídy
Někdy využijeme také nabídkovou lištu. Práce s ní je triviální, ještě o tom bude řeč. Dialog
Smysl této komponenty (představované třídou Rám
Pod tímto nepříliš výstižným termínem se skrývá okno s proměnnou velikostí.
Opět je to nativní objekt okenního systému. Ve Swingu ho reprezentuje třída
Vnitřní rám
Od předchozího se liší tím, že je to čistě objekt Swingu (není reprezentován
nativně) a může existovat jen uvnitř jiné swingové komponenty. Typicky se
používá pro dokumentová okna v MDI programech. Jedná se o třídu
Applet
Uvádím ho jen pro úplnost. Applet bývá umístěn na webové stránce a plní
podobné úkoly jako běžné okno. Třída má název Sestavení GUI aplikaceVytváříme-li GUI ručně (bez pomoci grafického návrháře ve vývojovém prostředí), je dobré si vše předem nakreslit na papír, nejlépe milimetrový. Takto si připravíme rozvržení aplikace a pak už jen implementujeme chování grafických komponent. Pokud nepotřebujeme pracovat s pevným rozmístěním komponent (a používáme správce rozložení, layout managery - bude o nich řeč v jednom z příštích dílů), je to ještě jednodušší a ruční práce je velice efektivní. Můžeme přímo používat již existující třídy nebo si od nich vytvářet potomky - druhá možnost je lepší v případech, kdy potřebujeme nějak zásadněji změnit chování některé komponenty nebo tehdy, chceme-li nějakou upravenou komponentu používat opakovaně. Příklad ruční tvorbyPusťme se nyní do tvorby aplikace. Na příkladu bude nejlépe vidět, jak se dá s GUI pracovat a jak to celé funguje. Budeme vytvářet jednoduchý textový editor - bude umět založit nový text, otevřít existující soubor a uložit data do zvoleného souboru. Kdo by chtěl nějakou funkci navíc (např. udržování názvu souboru v programu, automatické ukládání, dotaz na zahození neuložených dat, automatické zalamování řádků a podobně), jistě snadno přijde na to, jak to udělat.
Třída editoru bude odvozena od třídy public class Editor extends JFrame implements ActionListener { private JScrollPane sp = null; private JTextArea ta = null; private JMenuBar mb = null; private String sep = null;
Deklarujeme členské proměnné hlavních komponent. Není to nutné, ale pro
pozdější přístup se to hodí. Některé můžeme rovnou plně inicializovat, ovšem
pro lepší orientaci to ponechám na později. Ještě upozorním na proměnnou
Chvíli bych se zdržel u třídy public Editor() { super(); init(); } Konstruktor je jednoduchý a volá nejprve konstruktor předka a potom inicializační metodu. Do té je vhodné umístit všechno, co se týká inicializace komponenty. Můžeme pak mít více konstruktorů a z každého tuto metodu volat. public void init() { sep = System.getProperty("line.separator"); ta = new JTextArea(); Font f = Font.decode("Monospaced"); if (f != null) ta.setFont(f); sp = new JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); setContentPane(sp);
První část inicializační metody nejprve nastaví již zmíněný oddělovač řádků
do podoby, jaká odpovídá platformě (tedy na GNU/Linuxu to bude " JMenu menu= new JMenu("Soubor"); menu.setMnemonicv(KeyEvent.VK_S); JMenuItem mi = new JMenuItem("Nový", KeyEvent.VK_N); mi.setActionCommand("new"); mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK)); mi.addActionListener(this); menu.add(mi); mi = new JMenuItem("Otevřít...", KeyEvent.VK_O); vmi.setActionCommand("open"); mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK)); mi.addActionListener(this); menu.add(mi); mi = new JMenuItem("Uložit...", KeyEvent.VK_U); mi.setActionCommand("save"); mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK)); mi.addActionListener(this); menu.add(mi); mi = new JMenuItem("Konec", KeyEvent.VK_K); mi.setActionCommand("quit"); mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK)); mi.addActionListener(this); menu.add(mi); mb = new JMenuBar(); mb.add(menu); setJMenuBar(mb);
Tento poněkud delší úsek inicializátoru se zabývá přípravou nabídkové lišty.
Vytvoříme nabídku "Soubor" (žádné jiné nebudou), přidáme do ní potřebné položky
pro různé operace, a na závěr vytvoříme samotnou lištu a vložíme do ní menu.
Všimněte si několika věcí. Nabídka se bude otvírat zvolenou klávesou
(samozřejmě v kombinaci s
Opět malé zdržení - a to u třídy
Zvolené řešení reakce na výběr položek menu je jen jedno z mnoha. Kromě
rozlišení příkazu (action command) můžeme operace rozlišovat také podle
zdroje události. Jinou možností je vytvořit ke každé položce anonymní třídu
(implementující setTitle("Editor"); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setLocation(100, 100); setSize(400, 300); } Tyto příkazy by měl již každý znát. Nastavují titulek, výchozí zavírací operaci, polohu a velikost okna. Tím je inicializace dokončena. public void actionPerformed(ActionEvent e) { String s = e.getActionCommand(); if (s.equals("new")) clear(); else if (s.equals("open")) load(); else if (s.equals("save")) save(); else if (s.equals("quit")) dispose(); } Obsluha událostí od položek menu. Je to snad zřejmé na první pohled, porovnává se řetězec příkazu s definovanými hodnotami. Pro delší seznam by to bylo operačně náročné (a bylo by lepší použít jiný způsob rozlišení), zde nám to ale problémy nedělá. public void clear() { ta.setText(""); } Vytvoření "nového souboru". Spočívá prostě v tom, že se textová oblast vyprázdní. public void load() { JFileChooser fc = new JFileChooser(); fc.setDialogType(JFileChooser.OPEN_DIALOG); if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); ta.setText(""); try { BufferedReader br = new BufferedReader(new FileReader(f)); StringBuilder sb = new StringBuilder(); String s = ""; boolean fl = false; while ((s = br.readLine()) != null) { if (!fl) sb.append(sep); else fl = true; sb.append(s); } br.close(); ta.setText(sb.toString()); ta.setCaretPosition(0); } catch (IOException e) { JOptionPane.showMessageDialog(this, "Soubor nelze otevřít.", "Chyba", JOptionPane.ERROR_MESSAGE); } } }
Načtení textu ze souboru. Swing má svoji implementaci dialogu pro práci se
soubory. Dialog toho umí mnohem víc, než se zde používá (např. filtraci
souborů, vícečetné výběry), ale nám stačí základní operace. Pokud výběr
souboru proběhl správně (nedošlo k žádné chybě a uživatel potvrdil výběr),
načteme soubor. Možností je opět více. Zvolil jsem čtení pomocí textového
bufferovaného streamu po řádcích. Protože metoda
Nyní nastal čas upozornit na velice zajímavou a důležitou třídu - public void save() { JFileChooser fc = new JFileChooser(); fc.setDialogType(JFileChooser.SAVE_DIALOG); if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { BufferedWriter bw = new BufferedWriter(new FileWriter(f)); bw.write(ta.getText()); bw.close(); } catch (IOException e) { JOptionPane.showMessageDialog(this, "Soubor nelze uložit.", "Chyba", JOptionPane.ERROR_MESSAGE); } } } K tomu snad není potřeba nic dodat. Od metody k načtení dat se liší prakticky pouze tím, že se celý textový obsah uloží zavoláním jediné metody. Nyní už chybí pouze hlavní metoda pro spuštění programu: public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { Editor m = new Editor(); m.setVisible(true); } }); } Importy jsem jako obvykle vynechal. Po kompilaci a spuštění by se mělo objevit okno, které bude mít nahoře nabídkovou lištu. Ta bude fungovat obvyklým způsobem, pro ovládání půjde používat i klávesové zkratky. Tvoříme s pomocníkemToto byla ukázka kompletně ruční tvorby aplikace. Hlavně u větších programů s GUI je mnohdy efektivnější aspoň částečně využít grafické prostředí, ve kterém si GUI vytvoříme "klikacím způsobem". V následujících odstavcích budu hovořit o tvorbě téže aplikace v IDE NetBeans verze 5, jiná prostředí se používají podobně. Popis nebude ve stylu, aby to podle toho udělala cvičená opice - spíše vyzdvihnu důležité body.
Předpokládám již založený projekt a v něm nějaký balík. Začneme vytvořením
potomka
Pak se přepneme do zobrazení zdrojového kódu (Source). Vygenerovaný kód je
barevně označen, je sbalený a nelze do něj přímo zasahovat. Do souboru můžeme nyní vložit
metody
Zbývá už jen nastavit spouštění jednotlivých operací. Nejjednodušší je
pro každou položku přes kontextovou nabídku zvolit
Po dopsání implementace vygenerovaných metod je aplikace hotova (metoda
Seznamy, tabulky a stromyDosud jsme při tvorbě GUI využívali pouze jednoduché grafické komponenty. Mnoho programů ale vyžaduje používání různých seznamů (ať už obyčejných či rozbalovacích), stromů a tabulek. Zde se opět pořádně projeví výhody frameworku Swing, protože nám poskytuje velmi příjemné mechanismy pro práci s těmito grafickými komponentami a s daty, nad nimiž pracují. Příští díl seriálu bude kompletně věnován této oblasti, protože ta si takovou pozornost jednoznačně zaslouží.
|
Search Software
Search Google
|
||||||||||||||||||||||||||||||||||||||||||||||
©Pavel Kysilka - 2003-2024 | maillinuxsoft.cz | Design: www.megadesign.cz |