Image
22.6.2016 0 Comments

Java pod lupou I. /16.časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Balík java.awt (dokončenie)

V predchádzajúcom pokračovaní sme zabudli spomenúť ešte dve významnejšie pomocné triedy. Prvá z nich, Dimension, predstavuje zapuzdrenie šírky a výšky komponentu do jedného objektu. Druhá s názvom Toolkit je podstatne komplexnejšia a dá sa povedať, že reprezentuje implementáciu AWT. Nájdeme v nej množstvo metód na vytváranie natívnych komponentov, ale aj užitočné metódy getScreenSize() a getScreenResolution() na zistenie parametrov obrazovky, getImage(), createImage(), prepareImage()checkImage() na prácu s obrázkami, metódu beep(), ktorá generuje systémové „pípnutie“ a mnoho ďalších.

Menu komponenty

Na prácu s menu slúži skupina tried so spoločným predkom, abstraktnou triedou MenuComponent. Každý menu komponent má svoj názov, ktorý môžeme zistiť a nastaviť dvojicou metód (get|set)Name(). Metóda getParent() vracia rodičovský kontajner, v ktorom je zadaný komponent obsiahnutý, metódy (get|set)Font() slúžia na zistenie a nastavenie fontu použitého v menu komponente.

Obyčajné, ďalej nerozbaliteľné položky menu predstavuje trieda MenuItem. Pri konštrukcii položky zadávame ako parameter textový reťazec, ktorý sa zobrazí v menu. Tento reťazec môžeme neskôr zisťovať a nastavovať metódami (get|set)Label(). Položky môžu byť nastavené ako neaktívne (a obyčajne zobrazené svetlou, nevýraznou farbou) volaním metódy setEnabled(). Pomocou metód (get|set)ActionListener() môžeme k položke pripojiť príslušný listener.

Špeciálnym prípadom položky menu je trieda CheckboxMenuItem (odvodená od MenuItem). Tá obsahuje navyše binárny stav, indikovaný zaškrtávacou značkou. Stav môžeme zisťovať a nastavovať pomocou metód (get|set)State().

Základným typom menu kontajnera je trieda Menu, ktorá reprezentuje vertikálne menu. Jednotlivé položky menu musia byť typu MenuItem, a keďže samotná trieda Menu je potomkom triedy MenuItem, nie je problém vytvoriť hierarchickú štruktúru menu jednoduchým skladaním. Objekt triedy Menu má svoj názov a môže predstavovať oddeliteľné (tear-off) menu. Túto skutočnosť indikuje metóda isTearOff(). Z ďalších metód getItemCount() vracia počet položiek v kontajneri, getItem() sprístupňuje jednotlivé položky, add(), insert()remove() slúžia na pridávanie alebo odoberanie položiek. Špeciálnym typom položiek sú oddeľovacie pruhy, ktoré pridávame pomocou metód addSeparator()insertSeparator().

Vodorovný pruh s položkami menu implementuje trieda MenuBar. Jednotlivé položky musia byť typu MenuItem (plus všetkých jeho potomkov). Objekt triedy MenuBar sa pripája ku komponentom typu Frame pomocou metódy Frame.setMenuBar(). Na pridávanie a odoberanie položiek menu máme k dispozícii metódy add()remove(), počet položiek v menu zistíme volaním getMenuCount().

V AWT možno vytvárať aj kontextové menu, ktoré nemusia byť súčasťou vodorovného menu okna, ale môžu byť zobrazené na zadanej pozícii. Takéto menu sú objektmi triedy PopupMenu, ktorá je odvodená od Menu; zobrazenie menu má na starosti metóda show().

Ukážme si ešte krátky príklad, ako zostrojiť základné menu s dvoma podmenu FileHelp a s niekoľkými položkami (predpokladáme, že uvedený kód je súčasťou konštruktora okna – kompletný príklad možno tradične nájsť na webe):

Menu mnFile = new Menu("File");
mnFile.add(new MenuItem("New"));
mnFile.add(new MenuItem("Open..."));
mnFile.add(new MenuItem("Save"));
mnFile.add(new MenuItem("Save as..."));
mnFile.addSeparator();
mnFile.add(new MenuItem("Exit"));
 
Menu mnHelp = new Menu("Help");
mnHelp.add(new MenuItem("About..."));
 
MenuBar mb = new MenuBar();
mb.add(mnFile);
mb.add(mnHelp);
 
setMenuBar(mb);

Rozhrania java.awt

Z rozhraní balíka java.awt za zmienku stoja nasledujúce: Adjustable reprezentuje objekty, ktoré umožňujú zmenu číselnej hodnoty v stanovenom rozsahu. Z balíka java.awt je takým objektom trieda Scrollbar. Rozhranie ItemSelectable predstavuje objekty obsahujúce zoznam položiek, ktoré možno nejakým spôsobom „vybrať“ – ako napríklad triedy List, Checkbox či Choice.

Rozhranie MenuContainer implementujú všetky triedy, ktoré fungujú ako menu kontajnery. Okrem MenuMenuBar je to tiež trieda Frame a na účely prípadného rozširovania aj trieda Component.

Všetky triedy, ktoré dokážu rozmiestňovať komponenty v kontajneroch, implementujú rozhranie LayoutManager. Potomkom tohto rozhrania je LayoutManager2, opisujúci triedy, ktoré vedia rozmiestňovať komponenty aj na základe zadaných obmedzení.

Chyby a výnimky

Vážnu, neopraviteľnú chybu AWT indikuje objekt triedy AWTError, odvodenej od triedy Error. Tá, ako vieme, predstavuje chyby, pri ktorých sa nepredpokladá obnovenie normálnej činnosti programu a nie je nevyhnutné ich zachytávať. Bežné výnimky AWT sú naproti tomu signalizované triedou AWTException. Okrem nej nájdeme v balíku java.awt ešte výnimky FontFormatException (chyba vo formáte súboru s definíciou písma) a IllegalComponentStateException (indikuje neplatný stav komponentu).

Triedy udalostí

Ďalej sa budeme venovať podbalíku java.awt.event, ktorý obsahuje triedy a rozhrania určené na obsluhu udalostí GUI. Spoločným predkom pre triedy udalostí v AWT je trieda AWTEvent (patriaca však do balíka java.awt). Inštancie tejto triedy, resp. jej potomkov, nevytvára programátor, ale samotný systém ako reakciu na výskyt rôznych udalostí. Každý typ udalosti je identifikovaný celým číslom, uloženým v chránenom člene id. Jeho hodnotu zistíme pomocou metódy getID(). Veľmi často je nevyhnutné určiť konkrétny typ udalosti práve na základe jej identifikačného čísla.

„Akčné“ udalosti, ako napríklad kliknutie na objekt Button, reprezentuje trieda ActionEvent. Pomocou metódy getActionCommand() môžeme získať príkazový reťazec, asociovaný k akcii (rôzne tlačidlá budú mať obyčajne priradené rôzne reťazce, podľa čoho môžeme jednoducho identifikovať, ktoré tlačidlo bolo stlačené); metóda getModifiers() vracia stav modifikačných klávesov (Shift a pod.) v okamihu výskytu udalosti.

Trieda AdjustmentEvent predstavuje udalosti generované triedami, ktoré implementujú rozhranie Adjustable, ako napríklad trieda Scrollbar. Pomocou metódy getAdjustable() získame objekt, ktorý udalosť spôsobil, getValue() vracia aktuálnu „hodnotu“ objektu (pri posuvníku je to poloha jazdca) a getAdjustmentType() použijeme na bližšie určenie typu udalosti.

Ďalšia trieda ComponentEvent zastupuje udalosti, ako posun, zmenu veľkosti a viditeľnosti komponentu a podobne. Tieto udalosti sú určené len na informačné účely – systém sa postará o zodpovedajúce prekreslenie komponentov sám.

Trieda ComponentEvent má niekoľko potomkov. Prvým z nich je trieda ContainerEvent, ktorá predstavuje udalosti týkajúce sa kontajnerov (opäť je určená len na informačné účely). FocusEvent reprezentuje získanie a stratu fokusu (ak má komponent fokus, znamená to, že doň budú smerované všetky vstupy z klávesnice; fokus sa obyčajne znázorňuje vizuálne – ako bodkovaný obdĺžnik či silnejšie orámovanie).

Ďalší potomok InputEvent slúži ako spoločný predok pre udalosti vstupu z klávesnice alebo myši. Pomocou niekoľkých metód môžeme zistiť stav modifikačných klávesov v okamihu výskytu udalosti. Udalosti klávesnice bližšie špecifikuje odvodená trieda KeyEvent. Tieto udalosti sú troch typov: stlačenie klávesu, uvoľnenie klávesu a „vstup znaku“. Tretí typ udalosti býva dôsledkom výskytu prvých dvoch typov, v rôznych kombináciách (napríklad udalosti „vstup znaku A“ predchádzajú udalosti „stlačenie Shift“, „stlačenie a“, „uvoľnenie a“ a „uvoľnenie Shift“). Príslušný znak a jeho kód získame volaním metód getKeyChar()getKeyCode(), slovný ekvivalent kódu znaku (ako napríklad „F1“) volaním metódy getKeyText(). Ďalšie metódy setKeyChar(), setKeyCode()setModifiers() umožňujú zmeniť kód znaku, ako keby bol stlačený úplne iný kláves.

Udalosti myši, ako jej pohyb, prechod nad komponentom, stlačenie a uvoľnenie tlačidiel, sú reprezentované triedou MouseEvent. Polohu myši zistíme pomocou metód getX()getY(), počet kliknutí vracia metóda getClickCount() (jednoduché i dvojité kliknutie majú rovnaký identifikátor MOUSE_CLICKED, líšia sa v návratovej hodnote tejto metódy). Metóda isPopupTrigger() indikuje, či daná udalosť slúži ako povel na zobrazenie kontextového menu pre danú platformu.

Trieda PaintEvent existuje v súvislosti s prekresľovaním komponentov, používa ju však systém, nie programátor. Poslednou komponentovou udalosťou je trieda WindowEvent, indikujúca zmeny stavu okna (otvorenie, zavretie, maximalizáciu, minimalizáciu a pod.).

Udalosti súvisiace so zmenou hierarchie komponentov reprezentuje trieda HierarchyEvent, určená opätovne len na informačné účely. Udalosti označenia a odznačenia položky v objekte typu ItemSelectable (takým je napríklad trieda List) reprezentuje trieda ItemEvent. Príslušnú položku získame volaním metódy getItem(). Poslednou udalostnou triedou je TextEvent, ktorá indikuje zmenu textového obsahu v komponente.

Zachytávanie udalostí

Ako sme hovorili minule, jednotlivé komponenty AWT generujú rôzne množiny udalostí a iným objektom poskytujú možnosť reagovať na výskyt týchto udalostí. Objekt, ktorý sa chce dozvedieť o každom výskyte nejakého typu udalosti, pripojí k príslušnému komponentu tzv. listener. Sú v zásade dva spôsoby, ako vytvoriť listener: implementáciou príslušného „počúvacieho“ rozhrania alebo odvodením od niektorej adaptérovej triedy.

„Počúvacích“ rozhraní je spolu pätnásť a všetky sú odvodené od rozhrania EventListener (neobsahuje žiadne metódy, slúži len ako spoločný predok). Nebudeme ich tu všetky menovať, v zásade majú názvy korelujúce s metódami typu (add|remove)*Listener() jednotlivých komponentov. Jeden príklad za všetky: rozhranie ActionListener. Toto rozhranie musia implementovať všetky listenery, ktoré majú zachytávať „akčné“ udalosti, ako napríklad kliknutie na tlačidlo. Rozhranie tvorí jediná metóda actionPerformed(), ktorá je volaná v okamihu výskytu udalosti. Parametrom metódy actionPerformed() je objekt typu ActionEvent.

Treba mať na pamäti, že metóda actionPerformed() je súčasťou listenera a volá ju komponent, na ktorom k udalosti došlo. Vo všeobecnosti si každý komponent udržuje zoznam všetkých zaregistrovaných listenerov a pri výskyte niektorej udalosti ich všetkých informuje zavolaním ich príslušnej metódy.

Podobne vyzerajú aj ostatné „počúvacie“ rozhrania, môžu však obsahovať aj viac ako jednu metódu, na indikáciu rôznych podtypov udalostí (napríklad WindowListener obsahuje sedem metód, zodpovedajúcich siedmim podtypom udalosti WindowEvent). Určitou nevýhodou tohto spôsobu zachytávania udalostí môže byť nutnosť implementovať všetky metódy príslušného rozhrania, aj keď máme záujem iba o jeden podtyp udalosti. Malý príklad, ako pripojiť k tlačidlu akčný listener:

import java.awt.*;
import java.awt.event.*;
 
...
 
Button b = new Button("OK");
b.addActionListener(new ButtonWatcher());
 
...
 
class ButtonWatcher implements ActionListener
{
  void actionPerformed(ActionEvent e)
  {
    // ošetrenie udalosti
  }
}

(Dva riadky kódu, na ktorých sa vytvára nový objekt typu Button a pripája sa k nemu listener, budú, pochopiteľne, súčasťou nejakej metódy).

Druhým spôsobom zachytávania udalostí je použitie niektorej z adaptérových tried. Ide o osem abstraktných tried, ktoré implementujú vybrané počúvacie rozhrania. Metódy týchto tried sú implicitne prázdne. Ak od niektorej z tried odvodíme vlastný adaptér, postačí reimplementovať len tie metódy, o ktoré máme záujem (na rozdiel od počúvacích rozhraní, kde sme povinní implementovať všetky metódy). Názvy adaptérových tried sú podobné názvom počúvacích rozhraní, len namiesto slova Listener je Adapter. Adaptérové triedy existujú len pre rozhrania s viac ako jednou metódou.

Príklad použitia triedy WindowAdapter:

// nech f je inštanciou Frame
f.addWindowListener(new WindowWatcher());
 
...
 
class WindowWatcher extends WindowAdapter
{
  void windowClosing(WindowEvent e)
  {
    // reakcia na zavretie okna
  }
}
 

Treba mať na pamäti, že v praxi sa namiesto samostatných tried (ako sú ButtonWatcherWindowWatcher v našich príkladoch) častejšie používajú triedy vnorené alebo dokonca anonymné, takže sa stretneme napríklad so zápisom:

 
f.addWindowListener(new WindowAdapter
{
  void windowClosing(WindowEvent e)
  {
    // reakcia na zavretie okna
  }
});

K anonymným triedam sa však dostaneme až neskôr.

Práca s obrázkami

Ďalší podbalík java.awt.image poskytuje triedy určené na vytváranie a úpravu obrázkov. Ako abstraktná reprezentácia grafického obrázka slúži trieda Image (ktorá patrí do java.awt). Z dôležitých metód spomeňme getWidth()getHeight() na zistenie rozmerov obrázka a getSource() na získanie objektu, ktorý má na starosti vygenerovanie jednotlivých pixelov obrázka.

Na začiatku článku sme spomenuli triedu Toolkit, ktorá poskytuje niekoľko metód na vytvorenie a prácu s obrázkami. V balíku java.awt.image sa nachádzajú triedy určené pre komplexnejšie operácie. Práca s obrázkami je postavená na prúdovom modeli, ktorý zahŕňa „producenta“ obrázka (implementuje rozhranie ImageProducer), voliteľné filtre a „spotrebiteľa“ obrázka (implementuje rozhranie ImageConsumer).

Základom obrázkových filtrov je trieda ImageFilter, ktorá sa sama osebe javí ako spotrebiteľ obrázka. Táto trieda predstavuje prázdny filter a slúži len ako bázová implementácia. Praktickejšia je trieda CropImageFilter, ktorá dokáže pôvodný obrázok orezať na požadovanú veľkosť. Na jednoduchú zmenu rozmerov obrázka možno použiť triedu ReplicateScaleFilter, ktorá používa najjednoduchší možný algoritmus: opakuje riadky (pri zväčšovaní obrázka) alebo ich vynecháva (pri zmenšovaní). O niečo lepšie výsledky dáva trieda AreaAveragingScaleFilter, ktorá pri zmene rozmerov počíta priemerné hodnoty pixelov. Najzaujímavejšia je však abstraktná trieda RGBImageFilter, ktorá umožňuje filtrovať obrázky na základe zložiek RGB jednotlivých pixelov. Vzhľadom na jej abstraktnosť je jasné, že konkrétny filter treba naprogramovať reimplementáciou príslušných metód.

Na prepojenie producenta obrázka a niektorého z filtrov použijeme triedu FilteredImageSource. Tá sa sama tvári ako producent, takže v prípade nutnosti použiť viacero filtrov stačí triedy vhodne zreťaziť rovnakým spôsobom ako pri filtroch údajových prúdov.

Ostatné triedy spomeňme len stručne: ColorModel je abstraktná trieda na reprezentáciu farebných modelov. Jej konkrétne implementácie tvoria triedy ComponentColorModel (zložkový model, jednotlivé farebné zložky sú samostatnými údajmi), IndexColorModel (paletový systém, jednotlivé farby sú indexmi do zadanej farebnej palety) a DirectColorModel, ktorá je odvodená cez medzipotomka PackedColorModel (opäť zložkový model, jednotlivé zložky sú však skombinované do jedného údaja – napríklad model RGB565 v 16-bitových farebných režimoch).

Na reprezentáciu pixelového rastra slúži trieda Raster. Nad rastrami možno vykonávať rôzne operácie, ako afinné transformácie, konvolúcie a podobne. Údaje rastra sú uložené v objekte typu DataBuffer.

Ďalšie podbalíky

V balíku java.awt možno nájsť niekoľko ďalších podbalíkov, ale s ohľadom na rozsah článku sa im nebudeme podrobnejšie venovať. Takže len informatívne: balík java.awt.color obsahuje triedy na prácu s farebnými profilmi ICC. Balík java.awt.datatransfer poskytuje rozhrania a triedy na výmenu dát medzi aplikáciami (pomocou schránky – clipboardu). V balíku java.awt.dnd sa nachádzajú triedy potrebné na implementáciu mechanizmu drag-and-drop. Ďalší balík java.awt.font v súlade so svojím názvom poskytuje triedy a rozhrania na prácu s písmami a ich opisnými súbormi (fontami). Balík java.awt.geom obsahuje množstvo tried na prácu s dvojrozmernou grafikou. Balíky java.awt.imjava.awt.im.spi umožňujú zápis netradičných znakov (typicky japonských, čínskych či kórejských) pomocou tzv. vstupných metód. No a konečne v poslednom balíku java.awt.print nájdeme rozhrania a triedy na prácu s tlačiarňou.

Pri grafike zostaneme

Java 2 obsahuje okrem AWT ešte jeden grafický rámec s poetickým názvom Swing. Ten je o niečo bohatší a prispôsobiteľnejší. Viac si o ňom povieme v budúcom pokračovaní.

 

 

 


Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Ako zbaviť fotky hmly

08.12.2016 11:59

Hmla alebo dym sú často veľmi kreatívne nástroje. No všetkého veľa škodí. Fotka potom stráca kontrast a v podstate na nej nič nevidieť. Hmlu môžete neraz následnými úpravami odstrániť alebo zredukovať ...

Ako na to

Užitočné SW nástroje

08.12.2016 11:53

AllDup v4.0.3 Určenie: program na vyhľadávanie a odstraňovanie duplicitných súborov Vlastnosti: duplicitné súbory sa vyhľadávajú len na zvolených diskových jednotkách alebo len v rámci vybraných ...

Ako na to

Fotografovanie s bleskom

08.12.2016 11:47

Ak máte moderný fotoaparát so vstavaným alebo externým bleskom, zdá sa vám téma článku triviálna. Jednoducho nastavíte vhodný režim, vyberiete najlepšiu kompozíciu záberu, exponujete a o zvyšok sa už ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá