Kis projekt: Slideshow

A slideshow (diavetítés) annyiból áll, hogy előre elkészített képeket váltogatunk az ablakunkba. Ehhez kelleni fog:

Szerencsére ehhez már mindent tudsz, kivéve egy trükköt: egy JLabel képes kitenni egy képet is a szöveg mellé. Ha csak képet adunk meg neki, akkor pedig a JLabel teljes egészében csak a képet mutatja.

A képet egy Icon osztályban kell megadni... na és itt kezdődik pár apró malőr.

Az URL

Az URL jelentése Uniform Resource Locator, (azaz egyezményes erőforrás megtaláló? Jó okkal senki nem hívja magyarul). Ez egy szöveg, amit egy webböngésző címsorába beírva egy erőforrást (azaz képet, hangot, videót, szöveget) kapsz, mert ez a szöveg egyértelműen leírja, hogy a világ összes számítógépe közül épp melyiken és éppen hol lehet megtalálni a file-t.

Az alábbi URL például:

http://dongo.biz/jm/resource/budapest.jpg

azt mondja, hogy:

Ha egy webböngészőbe teszed ezt, akkor kapsz egy Budapest képet. Próbáld ki, vagy kattints ide: http://dongo.biz/jm/resource/budapest.jpg

Azt gondoltam ki, hogy az érdekesség kedvéért az Internetről vegyük a képeket, és hogy ne kelljen sokat vacakolni, pár képet előkészítettem a következő URL-eken:

http://dongo.biz/jm/resource/budapest.jpg
http://dongo.biz/jm/resource/salgotarjan.jpg
http://dongo.biz/jm/resource/newyork.jpg
http://dongo.biz/jm/resource/sanfrancisco.jpg

Természetesen, van egy URL osztály, aminek van egy konstruktora:

new URL("http://dongo.biz/jm/resource/sanfrancisco.jpg")

A kép betöltése

Sajnos azonban ez még nem kép, csak egy URL. Az URL-ről be kell olvasni a képet, ehhez az ImageIO osztály read metódusa való:

BufferedImage image=ImageIO.read(new URL("http://dongo.biz/jm/resource/sanfrancisco.jpg"))

Nagyon jó, csak ez még nem rakható a labelre, mert nem Icon hanem BufferedImage. (Miért van ennyiféle kép osztály... képtelenség!)

Szóval ezt át kell adni egy ImageIcon konstruktorának, és akkor már jók vagyunk:

Icon icon=new ImageIcon(ImageIO.read(new URL("http://dongo.biz/jm/resource/sanfrancisco.jpg")))

Rakjuk össze

public class Slideshow {
    public static void main(String[] args) throws MalformedURLException, IOException {
        JFrame frame=new JFrame();
        frame.setSize(220, 190);
        frame.setTitle("Helyek");
        frame.setLayout(null);
        frame.setVisible(true);

        JLabel label=new JLabel();
        label.setBounds(0,0,286,160);
        frame.add(label);

        label.setIcon(new ImageIcon(ImageIO.read(new URL("http://dongo.biz/jm/resource/salgotarjan.jpg"))));
    }   
}

Exception!

A képbetöltés exceptionöket tud dobálni, ha nem sikerült. Ezeket vagy lekezeljük a try..catch-al, vagy nem csinálunk semmit, és továbbdobjuk. A main melletti throws... felsorolás azt jelenti, hogy igazán szándékosan fogjuk ezeket tobább dobni.

Próbáld ki! No most ez a ronda képbetöltés elég ronda... mi lenne, ha csinálnánk egy getIcon metódust hozzá? Ha már itt vagyunk, a lehetséges exceptionokat is kapjuk el - ha például nincs Internet, vagy épp nincs meg a kívánt kép, akkor írjunk ki valamit, és adjunk vissza null-t. A null azt jelenti, hogy nincs.

public class Slideshow {
    public static void main(String[] args) {
        JFrame frame=new JFrame();
        frame.setSize(220, 190);
        frame.setTitle("Helyek");
        frame.setLayout(null);
        frame.setVisible(true);

        JLabel label=new JLabel();
        label.setBounds(0,0,286,160);
        frame.add(label);

        label.setIcon(getIcon("http://dongo.biz/jm/resource/salgotarjan.jpg"));
    }

    public static Icon getIcon(final String url) {
        try {
            return new ImageIcon(ImageIO.read(new URL(url)));
        } catch (Exception e) {
            // hoppá, nincs meg a kép
            System.out.println("Nincs meg a kép!"+e);
            return null;
        }       
    }
}

Töltsük be mind a négy képet, és tegyük be egy List listába! Próbaképpen a listában a 3. képet tegyük ki a labelbe:

public class Slideshow {
    public static void main(String[] args) {
        JFrame frame=new JFrame();
        frame.setSize(220, 190);
        frame.setTitle("Helyek");
        frame.setLayout(null);
        frame.setVisible(true);

        JLabel label=new JLabel();
        label.setBounds(0,0,286,160);
        frame.add(label);

        List<Icon> icons=new ArrayList<Icon>();
        icons.add(getIcon("http://dongo.biz/jm/resource/salgotarjan.jpg"));
        icons.add(getIcon("http://dongo.biz/jm/resource/budapest.jpg"));
        icons.add(getIcon("http://dongo.biz/jm/resource/newyork.jpg"));
        icons.add(getIcon("http://dongo.biz/jm/resource/sanfrancisco.jpg"));

        label.setIcon(icons.get(3)); // San Francisco
    }

    public static Icon getIcon(final String url) {
        try {
            return new ImageIcon(ImageIO.read(new URL(url)));
        } catch (Exception e) {
            // hoppá, nincs meg a kép
            System.out.println("Nincs meg a kép!"+e);
            return null;
        }       
    }
}

Most már csak a timer kell hozzá, ami automatikusan váltogatja a képeket!

public class Slideshow {
    public static void main(String[] args) {
        JFrame frame=new JFrame();
        frame.setSize(220, 190);
        frame.setTitle("Helyek");
        frame.setLayout(null);
        frame.setVisible(true);

        JLabel label=new JLabel();
        label.setBounds(0,0,286,160);
        frame.add(label);

        List<Icon> icons=new ArrayList<Icon>();
        icons.add(getIcon("http://dongo.biz/jm/resource/salgotarjan.jpg"));
        icons.add(getIcon("http://dongo.biz/jm/resource/budapest.jpg"));
        icons.add(getIcon("http://dongo.biz/jm/resource/newyork.jpg"));
        icons.add(getIcon("http://dongo.biz/jm/resource/sanfrancisco.jpg"));

        label.setIcon(icons.get(3));

        Timer timer=new Timer(1000, new ActionListener() {
            int index=0;
            @Override
            public void actionPerformed(ActionEvent e) {
                label.setIcon(icons.get(index));
                index++;
                if (index>=icons.size()) {
                    index=0;
                }
            }
        });
        timer.start();
    }

    public static Icon getIcon(final String url) {
        try {
            return new ImageIcon(ImageIO.read(new URL(url)));
        } catch (Exception e) {
            // hoppá, nincs meg a kép
            System.out.println("Nincs meg a kép!"+e);
            return null;
        }       
    }
}

Szóval, megy a timer. 1000 ms-onként ami pont 1 másodperc, meghívja a listenerjét. Ott beállítja a label képébe azt az ikont, aminek a sorszáma az index nevű változóban van.

Utána növeli az index változó értékét. Ha az index változó olyan nagy lenne, hogy nem létező elemre mutat (azaz ha 4 képünk van, akkor a 0..3 a lehetséges érték az indexnek, de 4 már nem), akkor kinullázza, így újra kezdi a képek vetítését.

Slideshow városokkal

Igazán nem rossz, ugye?

Feladat: Keress további képeket az Interneten, és tedd be a programba!

Egy webböngészőben bármely képre jobb gombbal kattintva Copy Image Address vagy a Kép helyének másolása vagy hasonló értelmű funkcióval kimásolja a vágólapra a kép URL-ét.

Mivel az URL nem csak uniform de universal is, ezért az Internet bármely képének ugyanúgy van URL-je, mint annak a néhány képnek amit eddig használtunk.