Hlavní navigace

Pohled pod kapotu JVM – zpracování událostí v knihovně SDLJava (dokončení)

Pavel Tišnovský 18. 3. 2014

V dnešním článku o jazyku Java i o jeho virtuálním stroji dokončíme problematiku práce s událostmi implementovanými v knihovně SDLJava. Na čtveřici demonstračních příkladů si ukážeme, jak lze naprogramovat aplikaci s oknem s měnitelnými rozměry i to, jak lze například registrovat ztrátu fokusu tohoto okna.

Obsah

1. Pohled pod kapotu JVM – zpracování událostí v knihovně SDLJava (dokončení)

2. Událost typu sdljava.event.SDLResizeEvent

3. Demonstrační příklad SDLTest36: detekce změny velikosti okna aplikace

4. Vykreslovací plocha při změně velikosti okna aplikace

5. Demonstrační příklad SDLTest37: vykreslování do okna s měnitelnými rozměry

6. Korektní způsob reakce na změnu velikosti okna aplikace

7. Demonstrační příklad SDLTest38: korektní způsob reakce na změnu velikosti okna aplikace

8. Událost typu sdljava.event.SDLActiveEvent

9. Demonstrační příklad SDLTest39: detekce získání a ztracení fokusu a detekce přesunu kurzoru myši do plochy okna aplikace

10. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů

11. Odkazy na Internetu

1. Pohled pod kapotu JVM – zpracování událostí v knihovně SDLJava (dokončení)

V předchozích částech seriálu o programovacím jazyku Java i o virtuálním stroji tohoto jazyka jsme si vysvětlili způsob práce s událostmi implementovanými v knihovně SDLJava. Připomeňme si, že události, tj. instance třídy sdljava.event.SDLEvent popř. tříd od sdljava.event.SDLEvent odvozených, vznikají například při stisku klávesy, posunu kurzoru myši v okně aplikace, uzavření okna aplikace atd. Typicky se události postupně načítají v nekonečné smyčce (event loop) z takzvané fronty událostí (event queue) a aplikace na ně odpovídajícím způsobem reaguje změnou stavu svých objektů – posunem spritu hráče na obrazovce apod. Typická smyčka událostí v sobě zahrnuje i test na událost typu sdljava.event.SDLQuitEvent, takže je možné korektně reagovat na žádost o ukončení aplikace. Podívejme se na jednoduchý příklad, který jsme již v mnoha obdobách mohli vidět v předchozích částech seriálu:

    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            if (event instanceof SDLActiveEvent) {
                // adekvátní reakce na tento typ události
            }
 
            if (event instanceof SDLMouseButtonEvent) {
                // adekvátní reakce na tento typ události
            }
 
            if (event instanceof SDLMouseMotionEvent) {
                // adekvátní reakce na tento typ události
            }
 
        }
    }

2. Událost typu sdljava.event.SDLResizeEvent

Knihovna SDL a zprostředkovaně i knihovna SDLJava se poměrně často používá pro implementaci her. Většinou hry využívají vybraný exkluzivní celoobrazovkový grafický režim, což hráčům umožňuje se plně soustředit na vlastní hru a nenechat se rozptylovat stále komplikovanějším desktopovým prostředím :-) Ovšem v některých případech může být preferováno spuštění aplikace využívající SDL/SDLJava v samostatném okně. Na tomto místě se musí programátor rozhodnout, zda bude mít toto okno pevnou velikost či zda uživatelům umožní velikost (libovolně) měnit. Pokud má být velikost primárního okna aplikace neměnitelná, použije se následující typický způsob inicializace grafického subsystému SDLJava:

    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo() throws SDLException {
        final long flags = SDLVideo.SDL_DOUBLEBUF;
        SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags);
    }

Sami si můžete vyzkoušet, že velikost okna by nemělo být možné měnit. V případě, že má být velikost okna měnitelná, je nutné při inicializaci grafického subsystému knihovny SDL/SDLJava přidat příznak SDLVideo.SDL_RESIZABLE, a to například následujícím způsobem:

    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo(int width, int height) throws SDLException {
        // potrebujeme vytvorit okno, u ktereho je mozne menit jeho velikost.
        final long flags = SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_RESIZABLE;
        SDLVideo.setVideoMode(width, height, GFX_BPP, flags);
    }

Po této inicializaci je však nutné, aby aplikace začala korektně reagovat na změnu velikosti okna, což konkrétně znamená, že musí zpracovávat události typu sdljava.event.SDLResizeEvent, které jsou do fronty událostí vloženy po každé změně velikosti okna (závisí na mnoha faktorech, zda je tato událost zapsána pouze při ukončení změny velikosti okna či v jeho průběhu – typicky je chování závislé na nastavení správce oken).

3. Demonstrační příklad SDLTest36: detekce změny velikosti okna aplikace

V dnešním prvním demonstračním příkladu pojmenovaném SDLTest36 je ukázáno základní zpracování události typu sdljava.event.SDLResizeEvent. Nejprve je provedena inicializace grafického subsystému s využitím příznaku SDLVideo.SDL_RESIZABLE a posléze se ve smyčce událostí detekuje událost typu sdljava.event.SDLResizeEvent. Pokud je tato událost ze smyčky událostí přečtena, jsou na standardní výstup vypsány nové rozměry okna zjištěné metodami SDLResizeEvent.getWidth()SDLResizeEvent.getHeight() – tyto hodnoty přitom reprezentují rozměry vnitřní plochy okna, což je hodnota, která je pro programátora mnohem důležitější, než vnější rozměry okna (dekorace oken je totiž záležitostí správce oken a nikoli vlastní aplikace). Smyčka událostí implementovaná v tomto demonstračním příkladu vypadá následovně:

    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            // zmena velikosti okna
            if (event instanceof SDLResizeEvent) {
                // pretypovani
                final SDLResizeEvent resizeEvent = (SDLResizeEvent)event;
 
                // precist novou velikost okna
                final int width = resizeEvent.getWidth();
                final int height = resizeEvent.getHeight();
 
                // vypsat informaci o zmene velikosti okna
                System.out.format("Window resized to: %dx%d pixels.\n", width, height);
            }
 
        }
    }

Podívejme se nyní na úplný zdrojový kód demonstračního příkladu SDLTest36:

import sdljava.SDLMain;
import sdljava.SDLException;
import sdljava.event.SDLEvent;
import sdljava.event.SDLKeyboardEvent;
import sdljava.event.SDLResizeEvent;
import sdljava.event.SDLKey;
import sdljava.event.SDLQuitEvent;
import sdljava.video.SDLVideo;
 
import sdljava.x.swig.SDLPressedState;
 
 
 
/**
 * Tricaty sesty demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Prace s udalosti typu SDLResizeEvent.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest36 {
 
    /**
     * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_WIDTH = 320;
 
    /**
     * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_HEIGHT = 240;
 
    /**
     * Bitova hloubka vybraneho grafickeho rezimu.
     * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit
     * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty)
     */
    private static final int GFX_BPP = 0;
 
    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo() throws SDLException {
        // potrebujeme vytvorit okno, u ktereho je mozne menit jeho velikost.
        final long flags = SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_RESIZABLE;
        SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags);
    }
 
    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            // zmena velikosti okna
            if (event instanceof SDLResizeEvent) {
                // pretypovani
                final SDLResizeEvent resizeEvent = (SDLResizeEvent)event;
 
                // precist novou velikost okna
                final int width = resizeEvent.getWidth();
                final int height = resizeEvent.getHeight();
 
                // vypsat informaci o zmene velikosti okna
                System.out.format("Window resized to: %dx%d pixels.\n", width, height);
            }
 
        }
    }
 
    /**
     * Spusteni osmeho demonstracniho prikladu.
     */
    public static void main(String[] args) {
        try {
            // inicializace knihovny SDLJava
            SDLMain.init(SDLMain.SDL_INIT_EVERYTHING);
 
            // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani
            initVideo();
 
            // smycka pro zpracovani udalosti
            eventLoop();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // musime obnovit puvodni graficky rezim
            // i v tom pripade, ze nastane nejaka vyjimka
            SDLMain.quit();
        }
    }
 
}

Skript pro překlad na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest36.java

Dávkový soubor pro překlad na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest36.java

Skript pro spuštění na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest36

Dávkový soubor pro spuštění na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest36

4. Vykreslovací plocha při změně velikosti okna aplikace

Při změně velikosti okna aplikace je sice korektně vytvořena událost typu sdljava.event.SDLResizeEvent, která je následně vložena do fronty událostí, ovšem další operace za programátora knihovna SDL ani knihovna SDLJava automaticky neudělá. Na toto chování je zapotřebí si dávat pozor, protože dokonce ani nedojde k modifikaci primární vykreslovací plochy (SDLSurface) vytvořené dříve voláním SDLVideo.setVideoMode(width, height, bpp, flags);. To mj. znamená, že rozměry primární vykreslovací plochy zůstanou stále stejné, což ve výsledku povede k tomu, že se při změně velikosti okna buď nevykreslí celá scéna (část jí bude zakryta), či se naopak v části okna zobrazí jen neměnné pozadí. Takové – většinou neočekávané – chování aplikace je ukázáno na následující trojici obrázků, v nichž je původní velikost okna i původní velikost primární vykreslovací plochy rovna 320×240 pixelům:

Obrázek 1: Originální scéna vykreslená do okna o vnitřních rozměrech 320×200 pixelů.

Obrázek 2: Tatáž scéna, ovšem při změně vnitřních rozměrů okna na 442×248 pixelů.

Obrázek 3: Stále tatáž scéna, ovšem při změně vnitřních rozměrů okna na 204×303 pixelů.

5. Demonstrační příklad SDLTest37: vykreslování do okna s měnitelnými rozměry

Chování popsané v předchozí kapitole je názorně ukázáno na dnešním druhém demonstračním příkladu nazvaném SDLTest37. Po spuštění tohoto příkladu se provede inicializace grafického režimu v metodě initVideo(). Vykreslení scény je provedeno v další metodě drawOnScreen(), která sice korektně vypočte velikosti vykreslovaných obdélníků z rozměrů primární kreslicí plochy, ovšem jak již z předchozí kapitoly víme, nejsou tyto rozměry automaticky aktualizovány. To mj. znamená, že se v metodě drawOnScreen() scéna stále vykresluje do plochy o rozměrech 320×240 pixelů:

    /**
     * Vykresleni obdelniku na obrazovku.
     */
    private static void drawOnScreen() throws SDLException {
        // ziskat rozmery obrazovky
        final int width = screen.getWidth();
        final int height = screen.getHeight();
 
        // barva vykreslovani
        long color;
 
        // vymazat pozadi
        color = screen.mapRGB(0, 100, 0);
        rect.x = BORDER;
        rect.y = BORDER;
        rect.width = width - BORDER * 2;
        rect.height = height - BORDER * 2;
        screen.fillRect(rect, color);
 
        // vykreslit obdelnik na obrazovku
        color = screen.mapRGB(255, 255, 64);
        rect.x = width >> 2;
        rect.y = height >> 2;
        rect.width = width >> 1;
        rect.height = height >> 1;
        screen.fillRect(rect, color);
 
        // nutno volat i v pripade, ze neni pouzit double buffering
        screen.flip();
    }

Za zmínku zde stojí upozornění na to, že objekt typu SDLRect je v celé aplikaci vytvořen jen jedenkrát při inicializaci třídy, což znamená, že se při překreslení scény nebude zbytečně vytvářet další objekt, který by bylo následně nutné dealokovat správcem paměti (GC). Podobným způsobem, který ovšem poněkud odporuje principům tvorby programů se zajištěním lokality proměnných, lze zajistit bezproblémový běh aplikace ve virtuálním stroji Javy, který nebude nucen často spouštět správce paměti (ani knihovna SDLJava zbytečně nevytváří nové objekty, a to dokonce ani při vzniku události).

Následuje úplný výpis zdrojového kódu demonstračního příkladu SDLTest37:

import sdljava.SDLMain;
import sdljava.SDLException;
import sdljava.event.SDLEvent;
import sdljava.event.SDLKeyboardEvent;
import sdljava.event.SDLResizeEvent;
import sdljava.event.SDLKey;
import sdljava.event.SDLQuitEvent;
import sdljava.video.SDLSurface;
import sdljava.video.SDLRect;
import sdljava.video.SDLVideo;
 
import sdljava.x.swig.SDLPressedState;
 
 
 
/**
 * Tricaty sedmy demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Prace s udalosti typu SDLResizeEvent - vykreslovani do okna s menitelnymi rozmery.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest37 {
 
    /**
     * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_WIDTH = 320;
 
    /**
     * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_HEIGHT = 240;
 
    /**
     * Bitova hloubka vybraneho grafickeho rezimu.
     * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit
     * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty)
     */
    private static final int GFX_BPP = 0;
 
    /**
     * Okraje uvnitr okna, ktere zustanou cerne.
     */
    private static final int BORDER = 10;
 
    /**
     * Objekt predsavujici kreslici plochu.
     */
    private static SDLSurface screen = null;
 
    /**
     * Promenna vyuzivana pri prekreslovani - nema smysl zbytecne trapit GC.
     */
    private static SDLRect rect = new SDLRect();
 
    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo() throws SDLException {
        // potrebujeme vytvorit okno, u ktereho je mozne menit jeho velikost.
        final long flags = SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_RESIZABLE;
        screen = SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags);
    }
 
    /**
     * Vykresleni obdelniku na obrazovku.
     */
    private static void drawOnScreen() throws SDLException {
        // ziskat rozmery obrazovky
        final int width = screen.getWidth();
        final int height = screen.getHeight();
 
        // barva vykreslovani
        long color;
 
        // vymazat pozadi
        color = screen.mapRGB(0, 100, 0);
        rect.x = BORDER;
        rect.y = BORDER;
        rect.width = width - BORDER * 2;
        rect.height = height - BORDER * 2;
        screen.fillRect(rect, color);
 
        // vykreslit obdelnik na obrazovku
        color = screen.mapRGB(255, 255, 64);
        rect.x = width >> 2;
        rect.y = height >> 2;
        rect.width = width >> 1;
        rect.height = height >> 1;
        screen.fillRect(rect, color);
 
        // nutno volat i v pripade, ze neni pouzit double buffering
        screen.flip();
    }
 
    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            // zmena velikosti okna
            if (event instanceof SDLResizeEvent) {
                // pretypovani
                final SDLResizeEvent resizeEvent = (SDLResizeEvent)event;
 
                // precist novou velikost okna
                final int width = resizeEvent.getWidth();
                final int height = resizeEvent.getHeight();
 
                // vypsat informaci o zmene velikosti okna
                System.out.format("Window resized to: %dx%d pixels.\n", width, height);
            }
 
        }
    }
 
    /**
     * Spusteni osmeho demonstracniho prikladu.
     */
    public static void main(String[] args) {
        try {
            // inicializace knihovny SDLJava
            SDLMain.init(SDLMain.SDL_INIT_EVERYTHING);
 
            // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani
            initVideo();
 
            // vykresleni sceny
            drawOnScreen();
 
            // smycka pro zpracovani udalosti
            eventLoop();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // musime obnovit puvodni graficky rezim
            // i v tom pripade, ze nastane nejaka vyjimka
            SDLMain.quit();
        }
    }
 
}

Skript pro překlad na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest37.java

Dávkový soubor pro překlad na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest37.java

Skript pro spuštění na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest37

Dávkový soubor pro spuštění na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest37

6. Korektní způsob reakce na změnu velikosti okna aplikace

Aby aplikace dokázala korektně reagovat na změnu velikosti okna, je nutné, aby se po každém přijetí události typu sdljava.event.SDLResizeEvent znovu inicializoval grafický režim a aby se tím pádem vytvořila nová primární kreslicí plocha. Metodu initVideo() je tedy nutné upravit tak, aby jako své parametry akceptovala požadované rozměry kreslicí plochy:

    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo(int width, int height) throws SDLException {
        // potrebujeme vytvorit okno, u ktereho je mozne menit jeho velikost.
        final long flags = SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_RESIZABLE;
        screen = SDLVideo.setVideoMode(width, height, GFX_BPP, flags);
    }

Následně se musí ve smyčce událostí po změně velikosti okna vytvořit nová primární kreslicí plocha, přičemž je korektní původní plochu dealokovat metodou SDLScreen.freeSurface(). Ihned poté se obsah okna musí překreslit voláním metody drawOnScreen():

    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            // zmena velikosti okna
            if (event instanceof SDLResizeEvent) {
                // pretypovani
                final SDLResizeEvent resizeEvent = (SDLResizeEvent)event;
 
                // precist novou velikost okna
                final int width = resizeEvent.getWidth();
                final int height = resizeEvent.getHeight();
 
                // vypsat informaci o zmene velikosti okna
                System.out.format("Window resized to: %dx%d pixels.\n", width, height);
 
                // vytvoreni nove kreslici plochy a prekresleni cele sceny
                screen.freeSurface();
                initVideo(width, height);
                drawOnScreen();
            }
 
        }
    }

Obrázek 4: Originální scéna vykreslená do okna o vnitřních rozměrech 320×200 pixelů.

Obrázek 5: Tatáž scéna, ovšem při změně vnitřních rozměrů okna na 468×214 pixelů.

Obrázek 6: Stále tatáž scéna, ovšem při změně vnitřních rozměrů okna na 204×380 pixelů.

7. Demonstrační příklad SDLTest38: korektní způsob reakce na změnu velikosti okna aplikace

Po úpravě zdrojového kódu demonstračního příkladu SDLTest37 podle popisu z předchozí kapitoly získáme novou aplikaci s odlišným chováním, která je zde pojmenována SDLTest38. Povšimněte si, že změny ve zdrojovém kódu aplikace jsou v tomto případě minimální, ovšem v reálných programech by bylo nutné provést mnohem větší zásahy, a to zejména v metodě, v níž se má překreslit obsah okna (tj. například kde se má vykreslit celý herní svět). Z tohoto důvodu je nutné pečlivě zvážit, zda se má vůbec povolit změna velikosti okna s vykreslovanou scénou či zda bude mít okno neměnné rozměry:

import sdljava.SDLMain;
import sdljava.SDLException;
import sdljava.event.SDLEvent;
import sdljava.event.SDLKeyboardEvent;
import sdljava.event.SDLResizeEvent;
import sdljava.event.SDLKey;
import sdljava.event.SDLQuitEvent;
import sdljava.video.SDLSurface;
import sdljava.video.SDLRect;
import sdljava.video.SDLVideo;
 
import sdljava.x.swig.SDLPressedState;
 
 
 
/**
 * Tricaty osmy demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Prace s udalosti typu SDLResizeEvent - vykreslovani do okna s menitelnymi rozmery.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest38 {
 
    /**
     * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_WIDTH = 320;
 
    /**
     * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_HEIGHT = 240;
 
    /**
     * Bitova hloubka vybraneho grafickeho rezimu.
     * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit
     * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty)
     */
    private static final int GFX_BPP = 0;
 
    /**
     * Okraje uvnitr okna, ktere zustanou cerne.
     */
    private static final int BORDER = 10;
 
    /**
     * Objekt predstavujici kreslici plochu.
     */
    private static SDLSurface screen = null;
 
    /**
     * Promenna vyuzivana pri prekreslovani - nema smysl zbytecne trapit GC.
     */
    private static SDLRect rect = new SDLRect();
 
    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo(int width, int height) throws SDLException {
        // potrebujeme vytvorit okno, u ktereho je mozne menit jeho velikost.
        final long flags = SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_RESIZABLE;
        screen = SDLVideo.setVideoMode(width, height, GFX_BPP, flags);
    }
 
    /**
     * Vykresleni obdelniku na obrazovku.
     */
    private static void drawOnScreen() throws SDLException {
        // ziskat rozmery obrazovky
        final int width = screen.getWidth();
        final int height = screen.getHeight();
 
        // barva vykreslovani
        long color;
 
        // vymazat pozadi
        color = screen.mapRGB(0, 100, 0);
        rect.x = BORDER;
        rect.y = BORDER;
        rect.width = width - BORDER * 2;
        rect.height = height - BORDER * 2;
        screen.fillRect(rect, color);
 
        // vykreslit obdelnik na obrazovku
        color = screen.mapRGB(255, 255, 64);
        rect.x = width >> 2;
        rect.y = height >> 2;
        rect.width = width >> 1;
        rect.height = height >> 1;
        screen.fillRect(rect, color);
 
        // nutno volat i v pripade, ze neni pouzit double buffering
        screen.flip();
    }
 
    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            // zmena velikosti okna
            if (event instanceof SDLResizeEvent) {
                // pretypovani
                final SDLResizeEvent resizeEvent = (SDLResizeEvent)event;
 
                // precist novou velikost okna
                final int width = resizeEvent.getWidth();
                final int height = resizeEvent.getHeight();
 
                // vypsat informaci o zmene velikosti okna
                System.out.format("Window resized to: %dx%d pixels.\n", width, height);
 
                // vytvoreni nove kreslici plochy a prekresleni cele sceny
                screen.freeSurface();
                initVideo(width, height);
                drawOnScreen();
            }
 
        }
    }
 
    /**
     * Spusteni osmeho demonstracniho prikladu.
     */
    public static void main(String[] args) {
        try {
            // inicializace knihovny SDLJava
            SDLMain.init(SDLMain.SDL_INIT_EVERYTHING);
 
            // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani
            initVideo(GFX_WIDTH, GFX_HEIGHT);
 
            // vykresleni sceny
            drawOnScreen();
 
            // smycka pro zpracovani udalosti
            eventLoop();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // musime obnovit puvodni graficky rezim
            // i v tom pripade, ze nastane nejaka vyjimka
            SDLMain.quit();
        }
    }
 
}

Skript pro překlad na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest38.java

Dávkový soubor pro překlad na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest38.java

Skript pro spuštění na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest38

Dávkový soubor pro spuštění na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest38

8. Událost typu sdljava.event.SDLActiveEvent

Posledním typem události, s nímž se v dnešním článku seznámíme, je událost reprezentovaná instancí třídy sdljava.event.SDLActiveEvent. Tato událost může vzniknout v několika případech, zejména při získání či naopak ztrátě fokusu klávesnice (tj. při změně okna, do něhož budou přenášeny stisky kláves) a taktéž ve chvíli, kdy kurzor myši opustí plochu okna aplikace popř. se do této plochy vrátí. Způsob reakce na tento typ událostí závisí čistě na logice aplikace – může být poměrně rozumné pozastavit hru ve chvíli, kdy je ztracen fokus klávesnice, například vlivem zobrazení nějakého modálního dialogu nebo při ručním přepnutí aktivního okna atd. Aby aplikace správně rozeznala, jaký typ události přesně vznikl, je nutné použít následující dvojici příkazů pro získání přesného typu události:

final int type = activeEvent.getSwigActiveEvent().getState();
final boolean gain = activeEvent.getSwigActiveEvent().getGain() == 1;

Proměnná type může nabývat tří hodnot:

Type Význam
SDLActiveEvent.SDL_APPACTIVE aktivace či deaktivace celé aplikace (systémově závislé)
SDLActiveEvent.SDL_APPINPUTFOCUS získání či ztráta fokusu klávesnice
SDLActiveEvent.SDL_APPMOUSEFOCUS kurzor opustil plochu okna či se do okna naopak vrátil

Rozlišení mezi získáním či ztrátou fokusu atd. je samozřejmě provedeno v závislosti na hodnotě proměnné gain.

9. Demonstrační příklad SDLTest39: detekce získání a ztracení fokusu a detekce přesunu kurzoru myši do plochy okna aplikace

V předchozí kapitole popsaný způsob přečtení informací o ztrátě nebo naopak o získání fokusu klávesnice/myši je implementován v dnešním posledním demonstračním příkladu nazvaném SDLTest39, jehož zdrojový kód je zobrazen pod tímto odstavcem. Pro jednoduchost je výpis přesného typu událostí implementován v rozhodovací konstrukci switch-case, která je v bajtkódu uložena efektivním způsobem a JIT překladač tuto konstrukci taktéž dokážou efektivně přeložit (většinou lépe než sekvenci příkazů if-then-else):

import sdljava.SDLMain;
import sdljava.SDLException;
import sdljava.event.SDLActiveEvent;
import sdljava.event.SDLEvent;
import sdljava.event.SDLKeyboardEvent;
import sdljava.event.SDLKey;
import sdljava.event.SDLQuitEvent;
import sdljava.video.SDLVideo;
 
import sdljava.x.swig.SDL_ActiveEvent;
import sdljava.x.swig.SDLPressedState;
 
 
 
/**
 * Tricaty devaty demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Zaklad prace s udalosti typu SDLActiveEvent.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest39 {
 
    /**
     * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_WIDTH = 320;
 
    /**
     * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna.
     */
    private static final int GFX_HEIGHT = 240;
 
    /**
     * Bitova hloubka vybraneho grafickeho rezimu.
     * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit
     * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty)
     */
    private static final int GFX_BPP = 0;
 
    /**
     * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani.
     */
    private static void initVideo() throws SDLException {
        final long flags = SDLVideo.SDL_DOUBLEBUF;
        SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags);
    }
 
    /**
     * Smycka pro zpracovani udalosti.
     */
    private static void eventLoop() throws SDLException {
        while (true) {
            // precist udalost z fronty
            SDLEvent event = SDLEvent.waitEvent();
 
            // vyskok ze smycky pro zpracovani udalosti pri vyskytu
            // udalosti typu SDLQuitEvent
            if (event instanceof SDLQuitEvent) {
                return;
            }
 
            // stisk ci pusteni klavesy
            if (event instanceof SDLKeyboardEvent) {
                // pretypovani
                final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event;
 
                // symbol/kod klavesy
                final int symbol = keyEvent.getSym();
 
                // ESC ukonci program
                if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) {
                    return;
                }
            }
 
            if (event instanceof SDLActiveEvent) {
                // pretypovani
                final SDLActiveEvent activeEvent = (SDLActiveEvent)event;
 
                // precist typ udalosti
                final int type = activeEvent.getSwigActiveEvent().getState();
 
                // ziskala aplikace fokus/kurzor mysi ci ji ztratila?
                final boolean gain = activeEvent.getSwigActiveEvent().getGain() == 1;
 
                switch (type) {
                    case SDLActiveEvent.SDL_APPACTIVE:
                        System.out.println("The application is " + (gain ? "" : "in") + "active");
                        break;
                    case SDLActiveEvent.SDL_APPINPUTFOCUS:
                        System.out.println("The application has " + (gain ? "gain" : "lost") + " input focus");
                        break;
                    case SDLActiveEvent.SDL_APPMOUSEFOCUS:
                        System.out.println("The application has " + (gain ? "gain" : "lost") + " mouse coverage");
                        break;
                    default:
                        System.out.println("Unknown SDLActiveEvent type!");
                        break;
                }
            }
        }
    }
 
    /**
     * Spusteni osmeho demonstracniho prikladu.
     */
    public static void main(String[] args) {
        try {
            // inicializace knihovny SDLJava
            SDLMain.init(SDLMain.SDL_INIT_VIDEO);
 
            // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani
            initVideo();
 
            // smycka pro zpracovani udalosti
            eventLoop();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // musime obnovit puvodni graficky rezim
            // i v tom pripade, ze nastane nejaka vyjimka
            SDLMain.quit();
        }
    }
 
}

Skript pro překlad na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest39.java

Dávkový soubor pro překlad na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest39.java

Skript pro spuštění na Linuxu:

#!/bin/sh
 
SDL_JAVA_LIBS=./sdljava-0.9.1/lib
 
java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest39

Dávkový soubor pro spuštění na Windows:

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest39

10. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů

Všechny čtyři dnes popsané demonstrační příklady byly společně s podpůrnými skripty určenými pro jejich překlad a následné spuštění uloženy do Mercurial repositáře dostupného na adrese http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/. Podobně jako tomu bylo i v předchozích osmi dílech tohoto seriálu, i ke dnešním příkladům jsou přiloženy skripty využitelné pro jejich překlad a spuštění. Navíc byly přidány i skripty využitelné ve Windows:

# Zdrojový soubor/skript Umístění souboru v repositáři
1 SDLTest36.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36.ja­va
2 SDLTest36_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36_com­pile.sh
3 SDLTest36_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36_com­pile_sys.sh
4 SDLTest36_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36_run­.sh
5 SDLTest36_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36_run_sys­.sh
6 SDLTest36_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36_com­pile.bat
7 SDLTest36_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest36/SDLTest36_run­.bat
     
8 SDLTest37.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37.ja­va
9 SDLTest37_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37_com­pile.sh
10 SDLTest37_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37_com­pile_sys.sh
11 SDLTest37_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37_run­.sh
12 SDLTest37_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37_run_sys­.sh
13 SDLTest37_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37_com­pile.bat
14 SDLTest37_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest37/SDLTest37_run­.bat
     
15 SDLTest38.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38.ja­va
16 SDLTest38_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38_com­pile.sh
17 SDLTest38_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38_com­pile_sys.sh
18 SDLTest38_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38_run­.sh
19 SDLTest38_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38_run_sys­.sh
20 SDLTest38_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38_com­pile.bat
21 SDLTest38_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest38/SDLTest38_run­.bat
     
22 SDLTest39.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39.ja­va
23 SDLTest39_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39_com­pile.sh
24 SDLTest39_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39_com­pile_sys.sh
25 SDLTest39_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39_run­.sh
26 SDLTest39_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39_run_sys­.sh
27 SDLTest39_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39_com­pile.bat
28 SDLTest39_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/78d3c6eb13b2/sdlja­va/SDLTest39/SDLTest39_run­.bat

11. Odkazy na Internetu

  1. glDrawArrays
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArrays­.xml
  2. glDrawElements
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­ts.xml
  3. glDrawArraysInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArraysIn­stanced.xml
  4. glDrawElementsInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­tsInstanced.xml
  5. Root.cz: Seriál Grafická knihovna OpenGL
    http://www.root.cz/serialy/graficka-knihovna-opengl/
  6. Root.cz: Seriál Tvorba přenositelných grafických aplikací využívajících knihovnu GLUT
    http://www.root.cz/serialy/tvorba-prenositelnych-grafickych-aplikaci-vyuzivajicich-knihovnu-glut/
  7. Best Practices for Working with Vertex Data
    https://developer.apple.com/li­brary/ios/documentation/3ddra­wing/conceptual/opengles_pro­grammingguide/Techniquesfor­WorkingwithVertexData/Techni­quesforWorkingwithVertexDa­ta.html
  8. SDL 1.2 Documentation: SDL_Surface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html
  9. SDL 1.2 Documentation: SDL_PixelFormat
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html
  10. SDL 1.2 Documentation: SDL_LockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html
  11. SDL 1.2 Documentation: SDL_UnlockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html
  12. SDL 1.2 Documentation: SDL_LoadBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html
  13. SDL 1.2 Documentation: SDL_SaveBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html
  14. SDL 1.2 Documentation: SDL_BlitSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html
  15. SDL 1.2 Documentation: SDL_VideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html
  16. SDL 1.2 Documentation: SDL_GetVideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html
  17. Class BufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/i­mage/BufferStrategy.html
  18. Class Graphics
    http://docs.oracle.com/ja­vase/1.5.0/docs/api/java/aw­t/Graphics.html
  19. Double Buffering and Page Flipping
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/doublebuf.html
  20. BufferStrategy and BufferCapabilities
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/bufferstrategy.html
  21. Java:Tutorials:Double Buffering
    http://content.gpwiki.org/in­dex.php/Java:Tutorials:Dou­ble_Buffering
  22. Double buffer in standard Java AWT
    http://www.codeproject.com/Ar­ticles/2136/Double-buffer-in-standard-Java-AWT
  23. Java 2D: Hardware Accelerating – Part 1 – Volatile Images
    http://www.javalobby.org/fo­rums/thread.jspa?threadID=16840&tstar­t=0
  24. Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
    http://www.javalobby.org/ja­va/forums/t16867.html
  25. How does paintComponent work?
    http://stackoverflow.com/qu­estions/15544549/how-does-paintcomponent-work
  26. A Swing Architecture Overview
    http://www.oracle.com/technet­work/java/architecture-142923.html
  27. Class javax.swing.JComponent
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html
  28. Class java.awt.Component
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html
  29. Class java.awt.Component.BltBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.BltBufferStrategy.html
  30. Class java.awt.Component.FlipBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.FlipBufferStrategy­.html
  31. Metoda java.awt.Component.isDoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html#isDoubleBuffe­red()
  32. Metoda javax.swing.JComponent.is­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#isDouble­Buffered()
  33. Metoda javax.swing.JComponent.set­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#setDouble­Buffered(boolean)
  34. Javadoc – třída GraphicsDevice
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsDevice.html
  35. Javadoc – třída GraphicsEnvironment
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsEnvironment.html
  36. Javadoc – třída GraphicsConfiguration
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsConfiguration.html
  37. Javadoc – třída DisplayMode
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Dis­playMode.html
  38. Lesson: Full-Screen Exclusive Mode API
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/
  39. Full-Screen Exclusive Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/exclusivemode.html
  40. Display Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/displaymode.html
  41. Using the Full-Screen Exclusive Mode API in Java
    http://www.developer.com/ja­va/other/article.php/3609776/U­sing-the-Full-Screen-Exclusive-Mode-API-in-Java.htm
  42. Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
    http://www.mobilefish.com/tu­torials/java/java_quickgu­ide_jvm_instruction_set.html
  43. The JVM Instruction Set
    http://mpdeboer.home.xs4a­ll.nl/scriptie/node14.html
  44. MultiMedia eXtensions
    http://softpixel.com/~cwrig­ht/programming/simd/mmx.phpi
  45. SSE (Streaming SIMD Extentions)
    http://www.songho.ca/misc/sse/sse­.html
  46. Timothy A. Chagnon: SSE and SSE2
    http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf
  47. Intel corporation: Extending the Worldr's Most Popular Processor Architecture
    http://download.intel.com/techno­logy/architecture/new-instructions-paper.pdf
  48. SIMD architectures:
    http://arstechnica.com/ol­d/content/2000/03/simd.ar­s/
  49. GC safe-point (or safepoint) and safe-region
    http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html
  50. Safepoints in HotSpot JVM
    http://blog.ragozin.info/2012/10/sa­fepoints-in-hotspot-jvm.html
  51. Java theory and practice: Synchronization optimizations in Mustang
    http://www.ibm.com/develo­perworks/java/library/j-jtp10185/
  52. How to build hsdis
    http://hg.openjdk.java.net/jdk7/hot­spot/hotspot/file/tip/src/sha­re/tools/hsdis/README
  53. Java SE 6 Performance White Paper
    http://www.oracle.com/technet­work/java/6-performance-137236.html
  54. Lukas Stadler's Blog
    http://classparser.blogspot­.cz/2010/03/hsdis-i386dll.html
  55. How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
    http://dropzone.nfshost.com/hsdis.htm
  56. PrintAssembly
    https://wikis.oracle.com/dis­play/HotSpotInternals/Prin­tAssembly
  57. The Java Virtual Machine Specification: 3.14. Synchronization
    http://docs.oracle.com/ja­vase/specs/jvms/se7/html/jvms-3.html#jvms-3.14
  58. The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4
  59. The Java Virtual Machine Specification: 17.4. Memory Model
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.4
  60. The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.7
  61. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  62. ASM Home page
    http://asm.ow2.org/
  63. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  64. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  65. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  66. BCEL Home page
    http://commons.apache.org/bcel/
  67. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  68. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  69. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  70. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  71. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  72. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  73. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  74. Javassist
    http://www.jboss.org/javassist/
  75. Byteman
    http://www.jboss.org/byteman
  76. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  77. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  78. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  79. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  80. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  81. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  82. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  83. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  84. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  85. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  86. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  87. Cobertura
    http://cobertura.sourceforge.net/
  88. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html
Našli jste v článku chybu?
Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Root.cz: 250 Mbit/s po telefonní lince, když máte štěstí

250 Mbit/s po telefonní lince, když máte štěstí

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: Dáte si jahody s plísní?

Dáte si jahody s plísní?

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu