Swing (Java)

Ukázka použití Swingu

Swing je knihovna uživatelských prvků na platformě Java pro ovládání počítače pomocí grafického rozhraní. Knihovna Swing poskytuje aplikační rozhraní pro tvorbu a obsluhu klasického grafického uživatelského rozhraní. Pomocí Swingu je možno vytvářet okna, dialogy, tlačítka, rámečky, rozbalovací seznamy atd.

Historie

Původní nástroj pro tvorbu grafického uživatelského rozhraní je Abstract Window Toolkit (AWT), vyvíjený firmou Sun Microsystems jako součást Javy. První verze vyšla v roce 1995, spolu s první verzí jazyka Java. Během dalšího vývoje se ale u AWT projevily chyby v návrhu a další problémy. Např. bylo závislé na platformě a tím porušovalo jeden z principů, na kterém je jazyk Java postaven. V roce 1997 Sun upustil od dalšího vývoje AWT a začal vyvíjet Swing.

Jako základ sloužily Internet Foundation Classes (IFC), vyvinuté Netscape Communications Corporation na konci roku 1996, jako nástroj pro tvorbu grafického uživatelského rozhraní pro Javu. V roce 1997 došlo ke spojení IFC a dalších technologií od Netscape a Sun Microsystems do Java Foundation Classes (JFC), jehož je Swing součástí.

Swing je vyvíjen jako kombinace AWT, IFC a dalších technologií.

Swing je nedílnou součástí Java SE od verze 1.2. Do té doby byl dostupný pouze jako knihovna k samostatnému stažení.

Hierarchie

Hierarchie tříd

Hierarchie tříd grafických komponent Swingu je založena na rodičích z AWT, jak ilustruje obrázek napravo.

Jako každá třída v Javě, i třídy grafického uživatelského rozhraní jsou potomky třídy Object.

Základním stavebním kamenem všech grafických komponent je třída Component. Instance třídy Component představují objekty, které mají svoji grafickou reprezentaci a mohou být zobrazeny na monitoru a interagovat s uživatelem. Všechno, co Java na monitoru nakreslí, je instance třídy Component. Různé ovládací prvky (tlačítko, zaškrtávátko, seznam, atd…) v AWT jsou definovány jako potomci třídy Component.

Od třídy Component je dále odvozena třída Container (kontejner). Kontejner je taková grafická komponenta, která v sobě může držet a kreslit ostatní grafické komponenty. Jakým způsobem se komponenty v kontejneru nakreslí, určuje tzv. správce rozložení (implementace rozhraní LayoutManager). V AWT jsou od třídy Container odvozeny různé prvky, např. třída Window nebo Panel.

Základním kamenem knihovny Swing je třída JComponent. Tato třída je rodičem každé swingovské komponenty. Jak je patrno z obrázku, JComponent je potomkem Container. Tudíž všechny swingovské prvky v sobě mohou držet další komponenty. Potomci třídy JComponent jsou samotné swingovské komponenty, jako je JButton (tlačítko), JList (seznam), JPanel (obecný panel), atd… Všechny swingovské komponenty mají před svým logickým názvem písmeno J, aby byly rozlišitelné od svých protějšků z AWT.

K této obecné hierarchii existují výjimky, a to jsou okna a obecně všechny nejvyšší kontejnery (top-level containers – okna, dialogy, applety). Okna jsou obecně potomci třídy Window, a nemohou proto být potomci třídy JComponent (v Javě nelze dědit od více tříd). Swingovské protějšky k Window a jeho potomků (Frame, Dialog, atd…) jsou definovány jako potomci těchto tříd s „J“ na začátku. Tj. hlavní swingovské okno JFrame je definováno jako potomek Frame.[1]

Těžké a lehké komponenty

AWT bylo koncipováno jako rozhraní mezi Javou a grafickým API platformy. Tj. všechny grafické komponenty byly přímo kresleny systémem a měly tedy nativní vzezření. Např. JVM na Windows využívala Win32 API (konkrétně knihovny gdi32.dll a další) ke kreslení AWT komponent. Tyto nativně vykreslené prvky se nazývají „těžké“ (v originále heavyweight), protože měly své vlastní nativní neprůhledné okno v systému. Na systém se spoléhaly i v dalších věcech, např. zajišťování pozice na ose Z (která komponenta je v popředí a která v pozadí).

Swing přináší jiný přístup, a to ten, že každá komponenta je sama zodpovědná za svůj vlastní vzhled a nespoléhá se na systém. Každá komponenta sama definuje, jak vypadá, a na požádání se namaluje na monitor. Samotné kreslení se odehrává přímo v Javě, a operačnímu systému se pouze předá hotový obrázek k namalování. Tomuto přístupu se říká „lehký“ (lightweight). To, jak komponenty budou vypadat, již tedy nezáleží na operačním systému.

Swing navíc přidává podporu pro dvojitou vyrovnávací paměť (double buffering), která umožňuje plynulé kreslení grafických prvků; pro podporu průhlednosti a částečné průhlednosti; pro optimalizované kreslení v případě překrývajících se komponent; a další technologie. Pro kreslení využívá další část JFC, a to Java 2D API.

Kreslení nejvyšších kontejnerů (oken, dialogů…) je ve Swingu převzato z AWT, tudíž okna jako taková jsou platformě závislá (nelze mít okno na platformě, která okna nepodporuje). Jejich vzhled ale konfigurovatelný je.[2]

Konfigurovatelný vzhled

Protože operační systém již ve Swingu nemá kontrolu nad tím, jak bude komponenta vypadat, je možné ve Swingu změnit vzhled, chování a některé další charakteristiky všech komponent pomocí tzv. Look and Feel („Vzhled a Pocit“).

Look and Feel je sada delegátů, které určují, jak bude která komponenta vypadat. Např. pro tlačítko (JButton) je to třída ButtonUI. Vždy, když se má komponenta namalovat, tak se zeptá vhodného delegáta, jak má v tomto Look and Feel vypadat, a namaluje se podle toho.

Look and Feel je dokonce vyměnitelný za chodu, tudíž je možné během chodu programu kompletně změnit to, jak program vypadá, protože se pouze změní třída zodpovědná za poskytování informací o vzhledu.

Implicitní Look and Feel je platformně nezávislý a vypadá stejně na všech platformách. Swing dále poskytuje různé Look and Feel pro všechny hlavní platformy, a lze nastavit, aby zavedl takové Look and Feel, které bylo naprogramováno na nativní vzhled na dané platformě.

Na Internetu se nachází ke stažení mnoho dalších verzí Look and Feel třetích stran, a je samozřejmě možné si nadefinovat vlastní Look and Feel.

Tato architektura vyměňování Look and Feel je blízká návrhovému vzoru Abstraktní továrna.[1]

Architektura MVC

Model – View – Controller (MVC) je typ softwarové architektury, kde je uživatelské rozhraní (View) odděleno od logiky programu (Model) řídící logikou (Controller). Tyto tři komponenty bývají často odděleny rozhraními, a tak modifikace jedné části má minimální vliv na ostatní části.


Ve Swingu má každý grafický objekt (tlačítko, seznam, rozbalovací menu…) svůj model v podobě rozhraní, který je na daném grafickém objektu nezávislý. Swing poskytuje implicitní implementaci modelu pro běžné využití, ale nic uživateli nebrání, aby si naprogramovat objekt s jiným modelem. Toto umožňuje uživateli změnit chování grafické komponenty, ale využívat její vzhled.

Například JList (seznam) má definovaný model pomocí rozhraní ListModel. Protože rozhraní je definované pro danou komponentu, ListModel poskytuje metody pouze pro čtení dat (to je vše, co JList potřebuje k vykreslení prvků). Implicitní implementace ListModelu je DefaultListModel, který přidávání a odebírání prvků ze seznamu již podporuje. Obecně ListModel představuje jednorozměrné pole prvků, ale programátor může dané rozhraní implementovat podle svých potřeb.

Model dále nabízí rozhraní pro komunikaci se zbytkem programu pomocí vyvolávání událostí. Ve zkratce, komponenta nabízí, že si k ní kdokoliv může přihlásit posluchače (tzv. listener) na různé události. Listener je pro danou komponentu definován obvykle jako nějaké rozhraní. Když v komponentě proběhne daná události (ať už ji vyvolal kdokoliv) – např. zmáčknutí tlačítka, vybrání položky, minimalizování okna, atd…, komponenta všem přihlášeným posluchačům odešle zprávu o provedené akci. Tato technologie přihlašování a odesílání zpráv je založena na návrhovém vzoru Observer.

Např. tlačítko vyvolává jedinou událost – obecnou akci, která nastane při zmáčknutí tlačítka. Kdokoliv se může stát posluchačem mačkání tlačítka tím, že implementuje rozhraní ActionListener. Po zaregistrování se k tlačítku bude daný objekt dostávat zprávy o mačkání tlačítka prostřednictvím metod definovaných v rozhraní ActionListener.

Jiné komponenty mohou definovat více událostí – např. strom (JTree) vyvolává události při rozbalení položky a při vybrání položky. Dále obecně všechny komponenty (protože jsou potomky různých tříd v komponentní hierarchii), definují další události – při změně vlastníka, při změně vlastnosti (property), při změně kontejneru, při klepnutí myší, při psaní textu, při změně zaměření (focus), atd…[1]

Další vlastnosti

Přístupnost (Accessibility)

Swing poskytuje možnost implementace přídavných technologií pro asistenci tělesně postižených lidí při práci s počítačem. Některé z nich jsou implementovány přímo ve Swingu, jako např. možnost přiřazení klávesových zkratek tlačítkům, nebo přeskakování mezi prvky formuláře pomocí tabulátoru.

Ostatní lze dodefinovat tím, že se implementuje rozhraní Accessible a poskytne instanci třídy AccessibleContext. Různé podpůrné technologie využívají toto API pro svou funkčnost.[3]

Serializovatelnost (Serializability)

Všechny komponenty grafického rozhraní jsou serializovatelné.

Více vláken (Multi-threading)

Ačkoliv samotný Swing nepoužívá pro svůj běh více vláken a není navržen pro používání vláken (není vláknově bezpečné – thread safe), podporuje více vláken svou architekturou. Např. poskytuje vlákno, které se nazývá Event dispatch thread, které je mimo jiné zodpovědné za spouštění dalších vláken, když nějaký prvek spustí nějakou událost. Je možné tedy oddálit spuštění události, popřípadě volat logiku programu v samostatném vlákně.[4]

Příklad

Tento výňatek z kódu zobrazí text „Hello World!“ v okně:

import javax.swing.JFrame;
import javax.swing.JLabel;

public class HelloWorld {

    public static void main(String[] args){
        // vytvoříme okno
        JFrame frame = new JFrame("Hello World example");
        // do okna přidáme text
        frame.add(new JLabel("Hello World!"));

        // okno zvětšíme do takové velikosti, aby se do něj vešly všechny komponenty
        frame.pack();
        // nastavíme, že po zavření okna dojde k ukončení programu
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // vycentrujeme okno doprostřed obrazovky
        frame.setLocationRelativeTo(null);

        // okno zobrazíme
        frame.setVisible(true);
    }
}

Reference

V tomto článku byl použit překlad textu z článku Swing (Java) na anglické Wikipedii.

  1. a b c Package javax.swing [online]. Oracle [cit. 2013-06-16]. Dostupné online. 
  2. FOWLER, Amy. Painting in AWT and Swing [online]. Oracle [cit. 2013-06-16]. Dostupné online. 
  3. How to Support Assistive Technologies [online]. Oracle [cit. 2013-06-16]. Dostupné online. 
  4. Lesson: Concurrency in Swing [online]. Oracle [cit. 2013-06-16]. Dostupné online. 

Externí odkazy