Java (24) - úvod do grafiky a GUI
Aplikace s grafickým uživatelským rozhraním, případně jinak užívající grafiku,
se v Javě tvoří s lehkostí a elegancí. Určitou daní za to jsou poněkud vyšší
nároky na procesor a hlavně na paměť - ty však lze vhodným návrhem a implementací
podstatně omezit. Právě proto máme dobrý důvod tvořit a používat grafické
aplikace v Javě, mají nám totiž skutečně co nabídnout.
24.4.2006 06:00 |
Lukáš Jelínek
| Články autora
| přečteno 79339×
Krátký výlet do historie
Když Java vznikala, její tvůrci ušili grafickou část velice horkou jehlou.
Původní návrh (jak API, tak "střev" grafických balíků) byl hodně nedokonalý,
neumožňoval snadné a systematické využití. Proto se již s JDK 1.0 vytvořila
u vývojářů jistá averze vůči javovské grafice. V dalších verzích však docházelo
k neustálému zlepšování, takže se Java brzy stala vhodnou platformou pro
tvorbu grafických aplikací.
Grafiku jako takovou a GUI nelze v Javě dost dobře oddělovat. Existují prostě
pohromadě, využívají stejné třídy. Proto je v tomto i dalších dílech seriálu
budu chápat jako jediný celek. Na odlišnosti včas upozorním.
AWT
První implementací grafiky byla knihovna zvaná Abstract Windowing Toolkit (AWT).
Objevila se hned na začátku (JDK 1.0) a její nepříjemné a nesystematické API
(byť s označením deprecated) přetrvává v Javě dodnes. Něco se stále používá,
ale jsou to spíš věci související s obecnou grafikou, a nikoli s GUI. V dalších
verzích bylo sice API přepracováno a podstatně rozšířeno, ale jiné nevýhodné
vlastnosti přetrvaly.
Filosofie AWT byla taková, že každá komponenta v Javě měla svůj nativní
protějšek v systému. Byl to tedy podobný model, jako dnes používají některé
GUI platformy v C/C++. I když se jednalo o abstraktní (platformově nezávislé)
rozhraní, přenositelnost byla problematická, vzhledem k rozdílným vlastnostem
nativní úrovně GUI.
Swing
Od verze 1.2 máme v Javě novou grafickou knihovnu zvanou Java Foundation
Classes (JFC), známou spíše pod názvem Swing (dále již budu používat jen toto
označení). Původní koncept byl zavržen, Swing byl vytvořen prakticky kompletně
na zelené louce (i když v sobě obsahuje AWT API). Základní vlastnosti lze
shrnout do těchto bodů:
-
Kompletní implementace v Javě. GUI není napasováno na nativní komponenty,
vše je zcela platformově nezávislé.
-
Intenzivní využití dědičnosti a kompozice. Komponenty GUI využívají objektové
vlastnosti Javy, složitější součásti jsou složeny či zděděny z jednodušších.
-
Výrazné využití rozhraní. Různé operace v komponentách GUI (kreslení, editace
apod.) se provádějí přes rozhraní. Standardní implementace lze nahrazovat
vlastními a měnit tak chování komponent.
-
Důsledné oddělení funkcionality od vzhledu GUI (look & feel). Témat vzhledu je několik
k dispozici přímo ve standardní knihovně, další si lze vytvořit a použít.
-
Oddělení dat od objektů GUI u složitějších komponent (strom, tabulka) pomocí
tzv. modelů. To opět zlepšuje možnosti přizpůsobení a také opakovanou
použitelnost komponent.
Uvedené vlastnosti, pro programátory velice příjemné, mají druhou stránku věci
- relativně vysoké nároky na rychlost procesoru a hlavně na paměť. V reakci
na to vznikly grafické knihovny, které se snaží tento problém odstraňovat.
Nejvýznamější z nich je SWT.
SWT
SWT (the Standard Widget Toolkit) je GUI knihovna s podobnými vlastnostmi,
jako má Swing, ovšem s nativní implementací grafických komponent. Kdo používá
IDE Eclipse nebo nějakou aplikaci na této platformě postavenou, s SWT se už setkal.
Proto též zajisté zjistil, že původní cíl vzniku, tedy snížení procesorové
a paměťové náročnosti, příliš naplněn nebyl a srovnatelné aplikace postavené
na SWT jsou zhruba stejně náročné jako ty používající Swing.
V čem tvořit?
Navrhovat a tvořit GUI pro javovské programy lze samozřejmě i bez nějakých
speciálních programů - návrh se připraví na papíře a příslušný kód se vytváří
přímo, bez pomocných nástrojů. Není to sice nijak zvlášť těžké a mnoho
vývojářů tak běžně pracuje (já občas také), ale pohodlná cesta to není. Pomocnou
ruku nám podají různá vývojová prostředí (IDE), která obsahují kromě jiného
i prostředky pro návrh GUI.
NetBeans
Po dřívějších neslavných výsledcích (z NB 3.x jsme leckdy získali nepříliš
fungující GUI) se návrh GUI v tomto IDE velice zlepšil. Zejména s poslední
verzí se pracuje výborně. V grafickém prostředí si lze vše snadno
sestavit, kostra kódu se vygeneruje automaticky a implementaci dopíšeme.
Generované části kódu jsou chráněny proti úpravám - to je současně výhoda i
nevýhoda, ostatně na to každý brzy přijde.
JBuilder
Nejnovější verze (2006) umí vynechat fázi generování kódu z návrhu GUI
a vytvořit místo toho přímo hotové třídy. To je výhodné pro rutinní práci,
pro cvičné účely je ovšem mnohem lepší nechat si kód vygenerovat. Práce
s JBuilderem je o něco snazší než s NetBeans (více podpůrných funkcí
pro tvorbu GUI), ale podle mého názoru je tento program (právě z tohoto důvodu)
pro začátečníky méně vhodný.
Ať už si zvolíte ten či onen program (existuje ještě řada dalších), vždy
mějte v počítači dostatek fyzické paměti. Rychlost procesoru není tak podstatná,
ale na paměti opravdu záleží.
Principy javovské grafiky a GUI
V celém následujícím výkladu (v této i dalších kapitolách) budu vše vztahovat
zásadně k technologii Swing. Jsou k tomu dobré důvody:
- Swing je součástí standardní instalace Javy.
- Velká platformová nezávislost a přenositelnost.
- Kvalitně navržené a systematické API.
- Větší počet existujících aplikací - více možností k učení se ze zdrojových
kódů.
Samozřejmě, kdo se dobře naučí Swing, nebude mít problém přejít na SWT,
případně na některou jinou implementaci GUI - hlavní vlastnosti se příliš
neliší. Taktéž se zde hodí znalosti s programováním GUI v jiném jazyce
(např. C++ a knihovny Qt).
Principy fungování GUI
Jak už je v moderních GUI zvykem, fungování aplikací je řízené událostmi.
Na programátorovi je, aby vyřešil reakce na tyto události. Ve Swingu to
funguje tak, že je zde smyčka obsluhující frontu asynchronních událostí
(ty přicházejí z okenního systému, např. X11), a odtud se volá obsluha těchto
událostí. Obslužné rutiny většinou volají další reakční metody vyšší úrovně,
až se nakonec obsluha události dostane do aplikace ke konečnému zpracování.
Pokud někdo např. najede myší na tlačítko, do fronty událostí se přidá událost
o pohybu myši. V obslužné smyčce se událost odebere a zavolá se metoda pro
její obsluhu. Tam se zjistí, že se kurzor myši dostal nad tlačítko, proto se
vytvoří nové události (pro pohyb myši a pro najetí do prostoru) a ty se "pošlou"
příslušnému tlačítku. Tlačítko každou z událostí zpracuje a nějak na ně
zareaguje - a potom vrátí řízení zpět, a tak se vše postupně dostane zase až
do obslužné smyčky. Detaily teď neuvádím, dostaneme se k nim později.
Co nás na tom hlavně zajímá? Obsluha každé události funguje tak, že máme
rozhraní pro reakci na událost, a toto rozhraní se nastavuje ve zdroji
příslušné události. Většinou může být více implementací rozhraní (a tedy více
reakcí) současně na stejnou událost, metody se zavolají postupně.
Jak se kreslí
Nebyla by to grafika, kdybychom nemohli nic nakreslit. Základní principy opět
nejsou nic neobvyklého. Ke kreslení používáme tzv. grafický kontext, což je
nějaká implementace abstraktního kreslicího rozhraní. O jakou konkrétní
implementaci se jedná, nás často vůbec nezajímá - proto lze naprosto stejně
kreslit na obrazovku, do paměti nebo na tiskárnu.
Při kreslení můžeme využívat širokou škálu nástrojů, které jsou ve standardní
knihovně k dispozici. Je dobré je používat do té míry, jak je to jen možné,
protože ve vztahu ke grafickému kontextu většinou poskytují maximální možnou
optimalizaci.
Zásady pro tvorbu GUI
Než přejdeme k praxi, dovolte mi ještě připomenout několik důležitých zásad,
bez kterých nelze rozumně programovat GUI v Javě. Opomenutí pak často vede
k právě takovým programům, kvůli kterým mnozí lidé Javu zavrhují.
-
Nevytvářet zbytečně nové instance, vytvořené používat opakovaně. Zejména se to
týká polí. Vytváření a rušení objektů je jednak dost náročné, a hlavně se rychle
zaplňuje paměť, kterou garbage collector uvolňuje jen zvolna.
-
Nic by se nemělo zbytečně překreslovat. Využívejte optimalizační možnosti
a nekreslete to, co určitě není vidět. Mnoho věcí si lze také připravit předem
a pak najednou zobrazit, namísto ustavičného překreslování.
-
Do objektů grafiky a GUI se smí sahat jen z jednoho jediného vlákna, zvaného
event-dispatching thread. Je to to vlákno, které obsluhuje frontu událostí.
Pokud potřebujete něco provést z jiného vlákna, jsou na to metody
invokeLater()
a invokeAndWait() , ještě o nich bude řeč. Je to proto, že mnohé grafické
třídy neobsahují (z výkonnostních důvodů) žádnou synchronizaci.
-
Neblokujte event-dispatching thread výpočetními operacemi nebo třeba čekáním
na data ze sítě, výkonný kód umístěte do jiných vláken (i když to znamená
dost práce navíc). Nemělo by se stát, že aplikace kvůli nějaké zdlouhavé
operaci zatuhne na dobu delší než stovky milisekund - uživatelé bývají velice
netrpěliví.
-
Pokud to jde, používejte pro obsluhu událostí normální (opakovaně používané)
pojmenované třídy namísto "chrlení" tříd anonymních, k čemuž někdy svádí
vývojová prostředí.
-
Důsledně se vyhýbejte zavrženým (deprecated) metodám, i když se chovají
úplně stejně jako metody modernější. Používání zastaralých metod znepřehledňuje
kód (důvodem k zavržení je často právě nevhodné pojmenování, vzniklé v dobách
JDK 1.0) a hlavně může v budoucnu způsobit nefunkčnost programu, když budou
příslušné metody odstraněny.
-
Ošetřujte výjimky co nejblíže místu vzniku, ale ne ve větším rozsahu, než je
nutné. Nezachycené asynchronní výjimky totiž nezpůsobí ukončení programu,
budou odchyceny v hlavní smyčce fronty událostí. Proto také při podezřelém
chování programu s GUI vždy nahlédněte do standardního chybového výstupu, zda
tam není informace o výjimce (včetně výpisu zásobníku volání).
-
Snažte se maximálně oddělovat data od GUI, ale současně zachovávejte logickou
konzistenci. Tam, kde se používají modely, je to
snadné. V ostatních případech (seznamy apod.) se s výhodou používá metoda
toString() , která poskytne textovou reprezentaci nějakého objektu a umožní
pracovat s referencemi na data. Potom je např. položka v seznamu spjata
s konkrétní instancí datového objektu a nemusí se nikam nic kopírovat.
-
U složitějších grafických struktur (stromy) zobrazujících velké množství dat
zvažte, zda je v daném případě lepší vybudovat celou strukturu na začátku,
anebo ji budovat podle činnosti uživatele.
-
Mějte na paměti, že zavřené okno se nerovná zrušené okno. Pokud okno nezrušíte,
bude existovat dál, se všemi výhodami a nevýhodami. Bude-li nějaký program
tvrdošíjně odolávat pokusům o ukončení, možná někde zůstává zavřené nezrušené
okno. Zruší-li se všechna okna a program už nemá nic jiného na práci, skončí.
První grafická aplikace
Tak to byla šedá a nudná teorie, proto se pusťme do první aplikace s GUI.
Bude obsahovat pouze jediné okno pevné velikosti, a na něm bude tlačítko Konec. Po stisknutí
tlačítka se - pochopitelně - aplikace ukončí. Vytvoříme si třídu MyDlg , která
bude odvozena od třídy javax.swing.JDialog (třída pro dialogová okna).
public class MyDlg extends JDialog implements ActionListener {
private JButton but = new JButton("Konec");
Deklarujeme tlačítko pro umístění na panel, hned ho též inicializujeme. Šlo by
použít i jinou cestu, nedeklarovat členskou proměnnou a tlačítko vytvořit až
později. To by byl ovšem tento objekt později obtížně přístupný, proto je zvykem
ve většině případů grafické objekty deklarovat v rámci třídy. Všimněte si
implementovaného rozhraní - umožňuje zpracovávat události z tlačítka.
public MyDlg() {
super();
setSize(200, 200);
setLocation(100, 100);
setResizable(false);
setModal(true);
setTitle("První GUI");
but.setSize(80, 30);
but.setLocation(60, 85);
getContentPane().setLayout(null);
getContentPane().add(but);
but.addActionListener(this);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
V konstruktoru zavoláme konstruktor rodičovské třídy - u tříd tohoto druhu to
děláme vždy, pokud nemáme dobrý důvod tak neučinit. Pak se nastaví rozměry
dialogu a jeho pozice na obrazovce, rozměry a relativní pozice tlačítka. Zakážeme
změnu velikosti a určíme, že dialog má být modální (tedy že dokud je otevřen,
komunikuje se s uživatelem pouze přes něj; zde je to nutnost, protože jinak
by program hned skončil, nemáme žádné hlavní aplikační okno).
Další dva řádky vypnou správce rozložení (layout manager) a vloží tlačítko
na plochu dialogu.
Tím je hotovo sestavení dialogu, nyní je potřeba nastavit zpracování událostí od
tlačítka. Než se k tomu ale dostaneme, upozorním ještě na poslední řádek.
Dialog má totiž zavírací tlačítko okna - a to ve výchozím stavu nedělá vůbec nic.
Protože uživatel logicky očekává, že se mu po stisku okno zavře, musíme nastavit
výchozí zavírací operaci, a tou bude samozřejmě zrušení okna (konstanta
DISPOSE_ON_CLOSE ).
public void actionPerformed(ActionEvent e) {
dispose();
}
Protože události od tlačíka budeme zpracovávat přímo ve třídě MyDlg , je nezbytné
implementovat rozhraní java.awt.event.ActionListener a tedy vytvořit příslušnou
metodu actionPerformed . Obsahuje jediné volání - zrušení dialogu.
Máme tedy hotovo vše, co je potřeba k funkci aplikace. Tedy až na hlavní
metodu. V ní se pouze vytvoří instance naší třídy a dialog se zobrazí.
V metodě vidíte, že manipulace s GUI je přenechána event-dispatching threadu.
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyDlg dlg = new MyDlg();
dlg.setVisible(true);
}
});
}
Potřebné importy (a také uzavírací závorku třídy) jsem neuvedl, pro fungování
programu je samozřejmě nezbytné je doplnit, případně pracovat s úplnou
specifikací tříd. Po kompilaci hotový program obvyklým způsobem spustíme:
java MyDlg . Měl by se zobrazit dialog s tlačítkem. Po stisku tlačítka (nebo
uzavíracího tlačítka) okna se dialog zavře a program skončí.
Stavební kameny
I když z uvedeného příkladu jednoduchého GUI programu je zcela zřejmé, že nejde
o nic těžkého, přesto se vyplatí dobře poznat některé třídy a rozhraní. Příští
díl bych chtěl věnovat těmto základním "stavebním kamenů" a jejich použití.
O praktické příklady nebude nouze.
Verze pro tisk
|
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|

Vyhledávání software

Vyhledávání článků
28.11.2018 23:56 /František Kučera Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1
12.11.2018 21:28 /Redakce Linuxsoft.cz 22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář
6.11.2018 2:04 /František Kučera Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
4.10.2018 21:30 /Ondřej Čečák LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář
18.9.2018 23:30 /František Kučera Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
9.9.2018 14:15 /Redakce Linuxsoft.cz 20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business.
Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář
12.8.2018 16:58 /František Kučera Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář
16.7.2018 1:05 /František Kučera Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář
Více ...
Přidat zprávičku
 Poslední diskuze
31.7.2023 14:13 /
Linda Graham iPhone Services
30.11.2022 9:32 /
Kyle McDermott Hosting download unavailable
13.12.2018 10:57 /
Jan Mareš Re: zavináč
2.12.2018 23:56 /
František Kučera Sraz
5.10.2018 17:12 /
Jakub Kuljovsky Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?
Více ...
|