1
Grafické rozhraní
Studijní cíl Tento blok je věnován vytváření programů s využitím grafického rozhraní (GUI). Vysvětlen bude základní filozofie pro vytváření aplikací s GUI ve srovnání s konzolovými aplikacemi. Text se bude postupně zabývat zobrazením hlavního okna aplikace, přidání ovládacích komponent a obsluha událostí. Na jednoduchých příkladech bude demonstrováno použití základních ovládacích komponent a jejich důležitých základních vlastností.
Doba nutná k nastudování
3-4 hodiny
Průvodce studiem Při studiu tohoto bloku se předpokládá, že student je zvládá základy programování v jazyce Java s využitím vývojového prostředí NetBeans.
1.1 Programování aplikací s GUI Jak již bylo naznačeno v definování studijního cíle pro tento blok, prostor bude věnován především základům vytváření aplikací s grafickým uživatelským rozhraním (GUI, Graphical User Interface). Základní náplní předmětu Počítačová grafika je především vysvětlení principů základních grafických algoritmů a samotná výuka tvorby aplikací GUI do náplně předmětu zapadá pouze okrajově. Vzhledem k tomu, že součástí předmětu Počítačová grafika je i implementace vybraných algoritmů a tvorba jednoduchých grafických aplikací, je nezbytné, aby studenti byli obeznámeni se základy vytváření GUI aplikací, které umožňují použití grafického režimu. Protože tento předmět volně navazuje na předmět Základy programování, v rámci kterého bylo programování vyučováno pouze s využitím konzolových aplikací, je nutné chápat tento blok jako nezbytný mezičlánek a přípravu k další výuce předmětu Počítačová grafika.
KST/IPOGR Počítačová grafika
1-1
Petr Veselý KST FEI Univerzita Pardubice
V současné době představuje v oblasti programování tvorba aplikací s grafickým rozhraním tzv. hlavní proud. Vytváření konzolových aplikací je okrajovou záležitostí, která je vyhrazena pouze pro specifické případy. Hlavní rozdíly mezi běžnou konzolovou aplikací a aplikací s GUI lze shrnout do dvou základních bodů: použití komponent (např. existence hlavního okna s ovládacími prvky) a událostmi řízené programování (to je sice možné realizovat i v konzolových aplikacích, ale není to běžné). Princip GUI aplikace je tedy postaven na používání komponent a komunikaci mezi nimi (případně mezi nimi a uživatelem).
1.2 Grafické rozhraní GUI poskytované knihovnami jazyka Java je nezávislé na zařízení (tlačítko bude nebo může vypadat stejně na monitoru stolního PC i např. na tabletu bez ohledu na typu použité grafické karty) a rovněž s ohledem na multiplatformnost programovacího jazyka Java je nezávislé i na OS. Je tvořeno tzv. komponentami, které jsou vizuální nebo nevizuální. Standardní komponenty jsou součástí knihoven AWT a JFC. Komponenty jsou uspořádány do hierarchické stromové struktury na základě dědičnosti, případně implementace rozhraní. Na základě existujících komponent si může programátor vytvořit vlastní komponenty s požadovanými vlastnostmi a požadovaným chováním. V současné době v Javě existují 2 rozhraní: AWT (Abstract Window Toolkit) je zastaralé, obsahuje komponenty závislé na prostředí a je relativně pomalé, v současné době je používáno především pro applety JFC (Java Foundation Class) novější, moderní rozhraní, založeno na AWT, obsahuje nevizuální komponenty (Java Beans) a vizuální komponenty (Swing). Další text se bude týkat výhradně rozhraní s komponentami Swing. KST/IPOGR Počítačová grafika
1-2
Petr Veselý KST FEI Univerzita Pardubice
1.3 Událostmi řízené programování Události (Event) řídí běh programu. Program je sestaven z jednotlivých komponent, které mohou být dle potřeby zobrazovány a během své existence mohou generovat různé události. Událost rovněž může vzniknout činností uživatele (prostřednictvím určité komponenty), nebo mlže být generována operačním systémem. Všechny události týkající se dané aplikace jsou umisťovány do fronty, ze které jsou postupně vybírány a obsluhovány. To znamená, že program není řízen sledem příkazů (od prvního k poslednímu) v metodě main, ale je vlastně řízen smyčkou obsluhující frontu událostí (zpráv). Na komponenty jsou navázáni posluchači (listener), registrující na jednotlivé události. Obsluha jednotlivých událostí (reakce na událost), tzv. obslužný kód (handlery) jsou umístěny v jednotlivých metodách. S problematikou událostmi řízeného programování úzce souvisí i problematika vláken a vícevláknových aplikací.
1.4 Vytvoření programu a spuštění Vytvoření programu s GUI lze shrnout do následujících kroků: Návrh vzhledu aplikace (návrh grafického rozhraní hlavní okno, rozmístění dalších komponent, vzhled komponent, …) Definování událostí, na které budou jednotlivé komponenty reagovat Vytvoření metod s obslužnými kódy jednotlivých událostí Propojení událostí a obslužných kódů Zabezpečení možnosti ukončení programu Spouštění programu lze shrnout do následujících kroků: Vytvoření instance aplikace včetně vytvoření fronty zpráv a spuštění obslužné smyčky (automaticky, programátor to nemusí řešit) KST/IPOGR Počítačová grafika
1-3
Petr Veselý KST FEI Univerzita Pardubice
Volání metody main (automaticky, programátor to nemusí řešit) Vytvoření instance hlavního okna Zobrazení hlavního okna
1.5 Základní komponenty Většina používaných komponent je potomkem třídy javax.swing.JComponent, která je potomkem java.awt.Container. Komponenty zle rozdělit do tří základních kategorií dle úrovně: Top-Level komponenty (JFrame, JDialog) Kontejnerové komponenty slouží k seskupování komponent, které jsou do tohoto kontejneru umístěny (JPanel, JScrollPane, JToolbar, JSplitPane, ad.) Základní komponenty (listy) – Swing Controls (JButton, JLabel, JRadioButton, JCheckBox, JTextArea, JTextField, JScrollBar, JComboBox, JMenu, JList, JProgressBar, ad.) Rovněž je třeba si uvědomit, že existují jak editovatelné (interaktivní) komponenty, tak komponenty pouze informativní (uživatel nemůže měnit jejich obsah).
1.6 Hierarchie komponent v aplikaci Jednotlivé komponenty každé aplikace je možno uspořádat do stromové struktury, která vyjadřuje hierarchické uspořádání jednotlivých komponent v aplikaci. Z této hierarchie je patrné která komponenta vlastní (obsahuje ve svém kontejneru) jiné komponenty. Na následujícím obrázku je ukázka hierarchie komponent z konkrétní aplikace. Ze stromu komponent je zřejmé, že na vrcholu je komponenta hlavní okno (jFrame), která ve svém kontejneru obsahuje tři panely (jPanelHlavni, jPanelParametry a jPanelOvladani) atd. KST/IPOGR Počítačová grafika
1-4
Petr Veselý KST FEI Univerzita Pardubice
Obrázek 1: Ukázka hierarchie komponent v aplikaci
1.7 Zobrazení okna Nejjednodušší aplikace s GUI (tak jak bylo již uvedeno) musí splnit pouze několik základních předpokladů vytvoření instance pro hlavní okno a jeho zobrazení. V následující ukázce je vytvořena aplikace, která po svém spuštění v metodě main: Vytvoří instanci hlavniOkno třídy JFrame pro hlavní okno Vytvoří instanci statickyText třídy JLabel pro nápis, který se bude zobrazovat na ploše hlavního okna Instanci statickyText vloží do kontejneru hlavního okna (hlavní okno se stává jeho vlastníkem a zabezpečuje např. jeho zobrazení) Pro hlavní okno se nastaví chování při pokusu o jeho uzavření Provede se implicitní nastavení rozměrů okna dle jeho obsahu Zobrazí se hlavní okno aplikace KST/IPOGR Počítačová grafika
1-5
Petr Veselý KST FEI Univerzita Pardubice
import javax.swing.JFrame; import javax.swing.JLabel; public class MainFrame { public static void main(String[] args) { JFrame hlavniOkno = new JFrame("Př_01 - Hlavni okno"); JLabel statickyText = new JLabel ("Hurá, první příklad je na světě..."); hlavniOkno.getContentPane().add(statickyText); hlavniOkno.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); hlavniOkno.pack(); hlavniOkno.setVisible(true); } } Kód 2: Ukázka vytvoření a zobrazení hlavního okna aplikace
Obrázek 3: Ukázka spuštěné aplikace
Další ukázka vytvoří hlavní okno aplikace se dvěma tlačítky, které budou automaticky rozmístěny dle konkrétního tzv. layoutu. Nastavení zobrazení může být v konstruktoru. Aplikace funguje, ale nic nedělá. Na rozmístění tlačítek má vliv použitý Layout. Bez použití layoutu bude druhé tlačítko přes celé okno. Komponenty lze přidávat i pomocí getContentPane().add(button1). Metoda pack() umožňuje přizpůsobení velikosti okna svému obsahu. import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; public class MainFrame extends JFrame { JButton btn1, btn2; MainFrame () { setTitle("Příklad zobrazení okna"); setLayout(new FlowLayout()); btn1 = new JButton("Tlačítko 1"); add(btn1);
KST/IPOGR Počítačová grafika
1-6
Petr Veselý KST FEI Univerzita Pardubice
btn2 = new JButton("Tlačítko 2"); add(btn2); setSize(300,100); } public static void main (String[] args) { new MainFrame().setVisible(true); } } Kód 4: Ukázka vytvoření a zobrazení hlavního okna s tlačítky
Obrázek 5: Ukázka spuštěné aplikace
1.8 Reakce na událost Události vytváří (vysílá) uživatel (prostřednictvím ovládací komponenty), nebo program nebo systém. Z hlediska programování je to objekt a jiný objekt tyto události zachycuje (posluchač, listener). Zachycovat může pouze objekt s implementovaným rozhraním Listener, kterého si vysílající objekt zaregistruje. V následujícím příkladu obsahuje hlavní okno tlačítko (JButton) a statický text (JLabel). Text ukazuje stav počítadla, které je reprezentováno proměnnou typu int. Pokud se stiskne tlačítko, je počítadlo inkrementováno a jeho nový stav je zobrazen pomocí statického textu.
Obrázek 6: Ukázka spuštěné aplikace počítadla
Událost stisknutí tlačítka je propojena na obsluhu této události metoda buttonPocitadloActionPerformed.
KST/IPOGR Počítačová grafika
1-7
Petr Veselý KST FEI Univerzita Pardubice
Realizace propojení: pomocí metody addActionListener je tlačítku přidán posluchač (ad-hoc vytvořená instance třídy ActionListener není pojmenována). Tento posluchač při svém vytváření definuje handler actionPerformed, což je metoda, která zabezpečí reakci na událost stisknutí tlačítka. Tato metoda navýšení počítadla a zobrazení textu neřeší sama, ale volá metodu buttonPocitadloActionPerformed. public class MainFrame extends JFrame { JButton btnPocitadlo; JLabel jLabelPocetStisknuti; static int pocitadlo = 0; MainFrame () { … btnPocitadlo = new JButton("Zvyš stav počítadla"); add(btnPocitadlo); jLabelPocetStisknuti = new JLabel("Stav počítadla: 0"); btnPocitadlo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { buttonPocitadloActionPerformed(e); } }); add(jLabelPocetStisknuti); } private void buttonPocitadloActionPerformed(ActionEvent e) { pocitadlo++; jLabelPocetStisknuti.setText("Stav počítadla: " + pocitadlo); } …. } Kód 7: Ukázka vytvoření obsluhy události
Pojmy k zapamatování GUI, komponenta, událostmi řízené programování, událost, posluchač, obslužná metoda
Otázky na procvičení 1. Jaké jsou základní rozdíly mezi konzolovou aplikací a aplikací s grafickým uživatelským rozhraním? 2. Jak funguje událostmi řízené programování? KST/IPOGR Počítačová grafika
1-8
Petr Veselý KST FEI Univerzita Pardubice
3. 4. 5. 6. 7. 8. 9. 10.
Co je to komponenta? Jaké jsou základní typy komponent? Jakým způsobem se zobrazí hlavní okno aplikace? Jak se vloží komponenty do kontejneru kontejnerové aplikace? Jakým způsobem se řeší odezva na událost? Co je to posluchač a jak se registruje? Jaké jsou typy posluchačů? Co je nutno nastavit v kódu, aby bylo možno aplikaci korektně ukončit?
Odkazy a další studijní prameny
http://owebu.bloger.cz/Programovani/Java-Grafika-59-dil http://java.sun.com/docs/books/tutorial/2d/index.html http://www.linuxsoft.cz/article.php?id_article=244 Herout, P. Učebnice jazyka Java. České Budějovice : Koop, 2008. Herout, P. Java a grafické uživatelské prostředí. České Budějovice : Koop, 2007.
KST/IPOGR Počítačová grafika
1-9
Petr Veselý KST FEI Univerzita Pardubice