/ janturon.cz / Výuka / Java / Tvorba prázdného okna

Tvorba prázdného okna

Postupně budeme doplňovat třídu PhoneList, viz předchozí lekci. Pro tvorbu grafického vzhledu (GUI - Graphical User Interface) budeme používat následující balíky - soubory knihoven:

Pro začátek použijeme třídu Frame z balíku java.awt, jejíž definici načteme příkazem import:

PhoneList.java import java.awt.Frame; //PhoneList dědí z Frame public class PhoneList extends Frame { public static void main(String args[]) { PhoneList application = new PhoneList(); } public PhoneList() { //super = odkaz na rodiče, zde Frame //super(...) = volání konstruktoru rodiče super("Phone List"); //this = odkaz na potomka, zde PhoneList this.setSize(320,200); //bez tohoto příkazu se okno nezobrazí this.setVisible(true); } }

Extends

Dědění (zapisované slovem extends za názvem třídy) znamená, že přebíráme všechny neprivátní členy z rodiče (zde Frame); nově vzniklé třídě se pak říká potomek.

Krom modifikátorů public a private lze použít ještě protected, což je totéž, co private, ale umožňuje přístup k členům v potomcích.

Třída Frame má dlouhý strom závislostí:

  1. Object všem třídám, které nemají rodiče, kompilátor automaticky doplní rodiče Object
  2. Component je rodič všech grafických prvků
  3. Container jsou grafické prvky, které mohou obsahovat další grafické prvky
  4. Window je kontejner nejvyšší úrovně (okno)
  5. Frame je okno s lištou s nadpisem a s posouvatelnými okraji

Spuštěním uvedeného kódu se vytvoří okno schopné všech akcí, na které jsme zvyklí u ostatních oken: maximalizace, minimalizace, změnu velikosti táhnutím za okraje, přesouvání, zobrazení ikony na liště, přepínání mezi aplikacemi - tyto činnosti řídí OS. Okno bohužel nelze zavřít :-) jediná možnost je zabít jeho proces.

Implements

Obsluhu události zavření okna (tj. křížek nebo Alt-F4) můžeme doprogramovat pomocí objektu třídy obsahující metodu windowClosing. Objektům obsahující metody, které jsou spouštěny událostí, se říká Posluchač (Listener). Posluchače událostí okna dodáme metodou addWindowListener (definované ve třídě Window). Ta očekává parametr typu WindowListener, což není třída, ale rozhraní (Interface). To se liší od třídy tím, že neobsahuje definice metod, pouze jejich deklarace (hlavičky). Třída, která toto rozhraní "zdědí" (správně implementuje (klíčové slovo implements) musí napsat definice všech jejích metod. Zatímco zdědit je možné nejvýše jednu třídu, implementovat lze libovolné množství rozhraní. Objekt typu rozhraní vytvoříme pomocí konstruktoru libovolné třídy, která toto rozhraní implementuje.

Budeme potřebovat definice WindowListener a WindowEvent z balíku java.awt.event(později mnohem více tříd). Nemusíme všechny importovat zvlášť, můžeme je našíst všechny pomocí hvězdičky:

PhoneList.java import java.awt.Frame; import java.awt.event.*; class WindowHandler implements WindowListener { public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowClosing(WindowEvent e) {System.exit(0);} public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} } public class PhoneList extends Frame { public static void main(String args[]) { PhoneList application = new PhoneList(); } public PhoneList() { super("Phone List"); this.setSize(320,200); WindowListener wl = new WindowHandler(); this.addWindowListener(wl); this.setVisible(true); } }

Adaptéry

U okna většinou potřebujeme zapsat pouze jednu metodu: windowClosing. Třída implementující rozhraní ale musí napsat všechny jeho metody. Museli jsme je proto do WindowHandler zapsat jeko prázdné. Povinnost psát kód, který nedodává žádnou funkčnost je antivzor Boilerplate ukazující na špatný návrh nebo na to, že se jazyk snažíme používat na něco, na co nebyl navržen. Tomuto nařčení se Java snaží bránit pomocí Adaptérů: "přizpůsobovačů" rozhraní.

V java.awt.event existuje třída WindowAdapter implementující tři rozhraní, mj. i WindowListener tak, že ponechává jejich metody prázdné. V naší třídě WindowHandler tak místo implementace WindowListener můžeme zdědit WindowAdapter a překrýt (hide, předefinovat) jen ty metody, které mají něco dělat:

WindowHandler stručněji class WindowHandler extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }

Anonymní třída

V celé aplikaci budeme vytvářet i volat objekt typu WindowHandler pouze jednou (stejně tomu bude i v případě obsluhy událostí ostatních grafických prvků). Java v tom případě umožňuje zkrácený zápis (který používají všechny grafické návrháře) definice přímo v místě volání. Kód aplikace lze proto zkrátit na

PhoneList, zkrácený kód import java.awt.Frame; import java.awt.event.*; public class PhoneList extends Frame { public static void main(String args[]) { PhoneList application = new PhoneList(); } public PhoneList() { super("Phone List"); setSize(320,200); // definice v místě volání addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setVisible(true); } }

Všimněte si, že ukazatel this. není nutný. Používá se tam, kde je kolize jmen datových položek s parametry či proměnnými metody nebo jako nápověda čtenáři kódu, že je to člen třídy.

Všechny třídy (včetně anonymních) se kompilují do samostatných .class souborů. Objektový kód naší anonymní třídy je v PhoneList$1.class. Pořadové číslo za dolarem určuje anonymní třídu v pořadí, v jakém jsou vytvářeny.