Jazyk Java Zavři to okno! V aplikacích s grafickým uživatelským rozhraním je obvyklé, že uzavřením hlavního okna ukončíme celou aplikaci. V Javě to ale - na rozdíl třeba od Windows - neplatí automaticky. Pokud v tomto jazyku programujete, jsou další řádky právě pro vás. Okno je instance třídy java.awt.Frame nebo javax.swing.JFrame a uzavření jakéhokoli okna - ať je instancí kterékoli z těchto tříd nebo jejich potomků - způsobí pouze jeho skrytí, nic víc. Program poběží dál a budeme ho muset ukončit např. stisknutím kombinace Ctrl+C v konzolovém okně. Současná Java ovšem nabízí celkem tři způsoby, jak zařídit, aby při uzavření okna odvozeného od JFrame skončila celá aplikace. Pro okna odvozená od třídy Frame lze použít pouze druhé dva. Podívejme se na možné postupy podrobněji. JDK 1.3 Asi nejjednodušší způsob nabízí JDK 1.3. Třída JFrame v něm obsahuje metodu public void setDefaultCloseOperation(int op); které jako parametr můžeme předat některou z konstant DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE, DISPOSE_ON_CLOSE a EXIT_ON_CLOSE. Poslední konstanta je definována přímo ve třídě JFrame, ostatní definice najdeme v rozhraní javax.swing.WindowConstants (a byly k dispozici už v JDK 1.2). Zavoláme-li tedy pro určitou instanci setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); uzavření tohoto okna způsobí, že aplikace skončí. (V případě potřeby je nutno doplnit identifikátor JFrame celým jménem balíku, tedy psát javax.swing.JFrame.EXIT_ON_CLOSE.) Vzhledem k tomu, že aplikace může vytvořit více oken téže třídy, voláme metodu setDefaultCloseOperation() typicky v místě, kde okno vytváříme, nikoli v konstruktoru třídy okna. Tato alternativa vypadá jednoduše a lákavě, ve skutečnosti se ale hodí jen v situaci, kdy chceme po stisknutí uzavírací ikony v záhlaví okna okamžitě skončit - a to je málokdy. Zpravidla se předtím chceme uživatele programu zeptat, zda chce opravdu skončit, chceme zkontrolovat, zda jsou uloženy soubory, v nichž došlo ke změně, atd. A to takto nejde. JDK 1.1 Patrně nejčastěji se používá možnost, která je k dispozici již od JDK 1.1 a která vypadá takto (předpokládáme, že frame je instance představující hlavní okno aplikace): frame.addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing(java.awt.event.WindowEvent e) { System.exit(0); } } ); Zde zaregistrujeme nového posluchače (příjemce) událostí okna. Příjemce těchto událostí musí, jak známo, implementovat rozhraní java.awt.event.WindowListener; toto rozhraní ovšem obsahuje sedm metod a my potřebujeme jen jednu z nich - windowClosing(). Proto použijeme pomocnou třídu java.awt.event.WindowAdapter, která implementuje všechny metody rozhraní, ovšem jako prázdné (jejich těla neobsahují žádné operace). Jako parametr metodě addWindowListener() předáme anonymní instanci anonymní vnitřní třídy, která je potomkem třídy WindowAdapter a ve které jsme předefinovali metodu windowClosing() (jedinou metodu, která nás zajímá). Tato metoda zavolá System.exit(0) a tím ukončí aplikaci. Sem lze vložit operace, které zjistí, zda chce uživatel opravdu skončit atd. Ve skutečnosti se obvykle používá nepatrně složitější varianta téhož postupu, která ale zpravidla vede k přehlednějšímu programu. Z těla metody windowClosing() zavoláme metodu, kterou nazveme např. slus() a která se postará o vše potřebné: frame.addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing(java.awt.event.WindowEvent e) { slus(); } } ); public void slus() { // ...ukončovací operace } Takovéto uspořádání umožní mj. použít tutéž metodu slus() i pro ukončení aplikace příkazem z nabídky, při stisknutí tlačítka ap. Všimněte si, že slus() je metoda třídy, ve které se příjemce událostí registruje, nikoli metoda tohoto příjemce. Přesto ji v metodě windowClosing(), tedy v metodě příjemce, voláme, aniž bychom ji museli kvalifikovat jménem instance. To proto, že metody vnitřní třídy mají v Javě plný přístup ke složkám a metodám vnější třídy (bez ohledu na přístupová práva). Poznamenejme, že s tímto způsobem ukončení aplikace při uzavření hlavního okna se setkáme v automaticky generovaném kódu v některých javských vývojových nástrojích - např. ve Forte for Java od firmy Sun. Uvedený postup může mít mnoho variant. Můžeme např. použít pojmenovanou instanci pojmenované vnitřní třídy. Lze si také představit, že třída okna implementuje rozhraní WindowListener a zaregistruje se jako posluchač; pak ovšem bude muset implementovat všechny metody tohoto rozhraní, i když je nebude potřebovat. Výsledný kód však nebude zpravidla příliš přehledný. JDK 1.0 Na konec jsme si ponechali možnost, která se používala už v JDK 1.0 (a je k dispozici dodnes), i když je asi nejméně šikovná. Zde musíme do konstruktoru třídy okna přidat příkaz enableEvents(AWTEvent.WINDOW_EVENT_MASK); jímž povolujeme vznik událostí v okně. Kromě toho musíme ve třídě okna předefinovat zděděnou metodu processWindowEvent(), která tuto událost zpracuje: protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } Parametrem této metody je instance třídy java.awt.event.WindowEvent, která v sobě nese mj. informaci o druhu události. Tuto událost musíme nejprve předat metodě předka; teprve pak pomocí metody getID() zjistíme, zda jde o uzavření okna, a pokud ano, ukončíme program. S touto možností se setkáme v automaticky generovaném kódu v některých vývojových nástrojích (např. ve všech dosavadních verzích JBuilderu od firmy Borland, a to vzdor tomu, že poslední verze JBuilderu používají JDK 1.3). Poznamenejme, že povolování událostí je nezbytné pouze u tříd odvozených od java.awt.Frame. Pro instance tříd odvozených od javax.swing.JFrame jsou události automaticky povoleny, takže volání metody enableEvents() je zbytečné. O tom se můžeme přesvědčit pomocí následujícího prográmku: import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Vokno extends JFrame { public Vokno() { //enableEvents(AWTEvent.WINDOW_EVENT_MASK); } protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if(e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } public static void main(String[] args) { Vokno vokno1 = new Vokno(); vokno1.setVisible(true); } } Tento program pouze vytvoří instanci třídy Vokno a zobrazí ji. Protože jsme třídu Vokno odvodili od JFrame, nevadí, že je volání metody enableEvents() v komentáři; po stisknutí tlačítka s křížkem v pravém horním rohu okna program skončí. Nahradíme-li však třídu JFrame třídou Frame a ponecháme-li volání metody enableEvents() v komentáři, budeme program muset ukončit stisknutím kombinace Ctrl+C v okně javské konzoly. M. Virius