4. díl - Programování jednoduchých Java GUI her - Obrázky

Java Tvorba her Programování jednoduchých Java GUI her - Obrázky

V této kapitole se naučíme pracovat s obrázky. Ukážeme si jak vytvořit instanci objektu Image, jak zjistit výšku a šířku obrázku a jak obrázek umísti do panelu.

Obrázky

import javax.swing.JFrame;

public class ZobrazeniObrazku extends JFrame {

    public ZobrazeniObrazku() {
        this.setTitle("Zobrazení Obrázku");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        KresliciPanel panel = new KresliciPanel();
        this.add(panel);

        this.setResizable(false);
        this.pack();
    }

    public static void main(String[] args) {
        ZobrazeniObrazku zo = new ZobrazeniObrazku();
        zo.setVisible(true);
    }
}

Přibyl nám jeden řádek kódu a to

this.setResizable(false);

, který způsobí to, že nelze změnit velikost okna.

Teď si vytvoříme třídu KresliciPanel, která bude načítat a vykreslovat zadaný obrázek.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class KresliciPanel extends JPanel {
    private Image obrazek;

    public KresliciPanel() {
        this.setPreferredSize(new Dimension(400, 300));
        this.setBackground(Color.white);

        ImageIcon ii = new ImageIcon(this.getClass().getResource("obrazek1.jpg"));
        obrazek = ii.getImage();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawImage(obrazek, 5, 5, this);
    }
}

Máme plno importů, ale kód zas až tak dlouhý není.

private Image obrazek;

Vytvoříme si proměnnou typu Image a přístupovými právy private. To znamená, že v této třídě je tato proměnná normálně dostupná. Z vnějšku třídy k ní ale přístup není. Což je správně. S touto proměnnou budu pracovat v této třídě, tak není vhodné, aby do ní byl přístup odněkud jinud. Ale zpět k naší proměnné. Ta je typu Image, což je abstraktní třída (nelze ji vytvořit přímo použitím new) reprezentující grafické obrázky.

ImageIcon ii = new ImageIcon(this.getClass().getResource("obrazek1.jpg"));

Protože objekt třídy Image nelze vytvořit přímo, použijeme třídu ImageIcon. Jako parametr konstruktoru dáme adresu k našemu obrázku.

this.getClass()

Metoda this.getClass() vrací třídu this objektu. V mém případě to znamená obrazky.Kresli­ciPanel, protože třídu KresliciPanel mám uloženu v balíčku obrazky.

getResource(String jemnoSouboru)

Tato metoda najde zdroj s daným jménem a vrátí jeho URL, čili adresu. Když to shrnu, tak getClass().get­Resource(String jmenoSouboru) vrátí URL adresu souboru, který se nachází ve stejném umístění jako třída, kde byl tento kus kódu spuštěn. Vrácená URL se předá do konstruktoru ImageIcon a vytvoří se objekt.

obrazek = ii.getImage();

ImageIcon nabízí metodu getImage(), která vrací objekt typu Image. A proč vlastně vytváříme objekt typu Image?

g.drawImage(obrazek, 5, 5, this);

Protože objekt Graphics, který nám umožňuje kreslit, má metodu drawImage, která potřebuje jako parametr objekt typu Image, který se vykreslí na zadané souřadnice x, y. Čtvrtým parametrem je ImageObserver, což je rozhraní. Kreslení obrázku je asynchronní. Pokud nejsou k dispozici kompletní data, informuje se komponenta přes rozhraní ImageObserver jakmile se data objeví. JPanel, a tím i naše odvozená třída, implementuje toto rozhraní.

A tady je výsledek našeho snažení.

Vykreslení obrázku na panel v Java Swing

Ale určitě by to mohlo lépe vypadat.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class KresliciPanel extends JPanel {

    private Image obrazek;
    private int obrazekSirka;
    private int obrazekVyska;

    public KresliciPanel() {

        ImageIcon ii = new ImageIcon(this.getClass().getResource("obrazek1.jpg"));
        obrazek = ii.getImage();

        obrazekSirka = obrazek.getWidth(this);
        obrazekVyska = obrazek.getHeight(this);

        int x = 20 + obrazekSirka + 20;
        int y = 20 + obrazekVyska + 20;
        Dimension rozmerPanelu = new Dimension(x, y);

        this.setPreferredSize(rozmerPanelu);
        this.setBackground(Color.WHITE);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawImage(obrazek, 20, 20, this);
    }
}

Výsledek je následující.

Vykreslení obrázku na panel v Java Swing
private Image obrazek;
private int obrazekSirka;
private int obrazekVyska;
private Rectangle ramObrazku;

Vytvořím si čtyři privátní proměnné. Jedna bude reprezentovat načtený obrázek, další dvě šířku a výšku obrázku a poslední obrysový obdélník okolo obrázku.

ImageIcon ii = new ImageIcon(this.getClass().getResource("obrazek2.jpg"));
obrazek = ii.getImage();

Získání obrázku se provádí stejně jako v předchozím případě.

obrazekSirka = obrazek.getWidth(this);
obrazekVyska = obrazek.getHeight(this);

Třída Image nabízí metody pro zjištění šířky a výšky obrázku. Jako parametr požadují obě metody ImageObserver. Místo instance ImageObserveru je možné uvést null.

int x = 20 + obrazekSirka + 20;
int y = 20 + obrazekVyska + 20;
Dimension rozmerPanelu = new Dimension(x, y);

this.setPreferredSize(rozmerPanelu);

Rozměr panelu nastavíme na šířku a výšku obrázku + okraje po všech stranách 20px.

g.drawImage(obrazek, 20, 20, this);

Obrázek vykreslíme na zadanou pozici (levý horní bod bude na souřadnicích: x = 20, y = 20).


 

Stáhnout

Staženo 383x (104.88 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

  Aktivity (1)

Článek pro vás napsal vita
Avatar
vita

Jak se ti líbí článek?
Celkem (2 hlasů) :
55555


 



 

 

Komentáře
Zobrazit starší komentáře (1)

Avatar
Iwitrag
Člen
Avatar
Iwitrag:

Nějak jsem nepobral, na co se tvoří ten rám obrázku...
A trošku mi tam chyběla zmínka o tom, jak vlastně vložit ten obrázek do NetBeans...

  1. Přetáhnout ho do projektu třeba z pruzkumníka
  2. CTRL+C (např. v průzkumníku) a CTRL+V (v NetBeans)
  3. Vložit přímo do projektové složky kde máme třídy (src)

Možná Vám to přijde jako jasná věc, ale pro nováčky (jako jsem já) to zas tak jasné být nemusí, asi 5 minut jsme hledal různě v nabídkách, něco jako New -> Image :D

Ale jinak super :) Docela rozdíl např. od GML, kde stačí napsat jen draw_image(img, x, y) a vše je hotovo :D

Editováno 17.1.2014 22:17
Odpovědět 17.1.2014 22:16
Učím se ostře vidět.
Avatar
TomBen
Redaktor
Avatar
Odpovídá na Iwitrag
TomBen:

Pleteš se jak v Javě, tak v GML. I když javu nedělám, jde tu zjevně o načítání resources ze souboru a odpovídající kód v GML je tedy:

background_add(filename, removeback, smooth);
draw_background(background, x, y);

Pokud bys chtěl mít taky okno velké podle obrázku a centrované, musel bys přece jen nějaký ten kód přidat. GML není tak jednoduchý jazyk, jak vypadá. Ve snaze o srozumitelnost davům jsou v něm některé věci velmi těžko vytvořitelné. Ne nemožné, jen velmi, velmi těžké. Asi tak, jako by to bylo u ostatních jazyků nebýt knihoven.

BTW: draw_image neexistuje v gml vůbec

Editováno 18.1.2014 4:01
Odpovědět 18.1.2014 3:59
Za posledních 200 miliónů let se nic zvláštního nestalo, akorát dinosauři vymřeli a opice se naučily programovat.
Avatar
Iwitrag
Člen
Avatar
Odpovídá na TomBen
Iwitrag:

Ale notak :D nechytej mě za slovo... samozřejmě jsem měl na mysli draw_sprite, ale ne každý kdo nedělá v GM ví, že sprite = obrázek... mě šlo spíš o to zdůraznit, jak moc se ty dva jazyky liší co do obtížnosti :)

A pořád si trvám na tom draw_sprite než-li na načítání z externích souborů, protože i ten obrázek v Javě vkládáme přímo do projektu a načítáme ho z podobného prostoru, kde jsou uloženy samotné třídy...
Tak samo v GM - první vytvoříš sprite, který vložíš přímo do aplikace a pak ho jen "nakreslíš" na obrazkovku :)

Odpovědět 18.1.2014 11:36
Učím se ostře vidět.
Avatar
TomBen
Redaktor
Avatar
Odpovídá na Iwitrag
TomBen:

Nesouhlasím s lecčíms z toho, co píšeš, ale tady to spamovat nechci. Přečetl jsem si, co sis dal na zeď a tvůj názor je jasný. Protože jde zároveň o pózu, tak z něj nemůžeš ustoupit i kdybys chtěl a tím debata zřejmě ztrácí smysl. Ok, budu tě brát tak, jaký jsi a pokud se udržíš jen v mezích osobního názoru, nebudu to dál řešit. Nicméně, kdybys měl o nějakou debatu zájem, klidně otevři diskuzi v GM sekci. Budeš-li mít argumenty, rád budu oponovat. Už jsem dlouho nepokecal s nikým, kdo zvládne alespoň i/y na správných místech. :-)

Odpovědět 18.1.2014 13:29
Za posledních 200 miliónů let se nic zvláštního nestalo, akorát dinosauři vymřeli a opice se naučily programovat.
Avatar
Ondrca
Redaktor
Avatar
Ondrca:

Ahoj, co přesněji znamená - getClass a getResource? Díky

Odpovědět 3.2.2014 21:43
Zase jsem o něco chytřejší
Avatar
vita
Redaktor
Avatar
Odpovídá na Ondrca
vita:

this.getClass()­.getResource("o­brazek1.jpg") vrátí URL, kde se nachází obrazek1.jpg. Tento zdroj (obrazek1.jpg) se hledá v místě (package), kde se nachází aktuální třída (this.getClass()). Výsledná URL se předá jako parametr konstruktoru ImageIcon.
ImageIcon ii = new ImageIcon(this­.getClass().get­Resource("obra­zek1.jpg"));

Editováno 6.2.2014 20:57
 
Odpovědět 6.2.2014 20:56
Avatar
blrizzard
Člen
Avatar
blrizzard:

Nevíte co je za problém? Mám to stejně jako tu.
Exception in thread "main" java.lang.NullPo­interException
at javax.swing.I­mageIcon.<init>(Un­known Source)
at JavaImages.Ja­vaImage.<init>(Ja­vaImage.java:19)
at JavaImages.Ja­vaShow.<init>(Ja­vaShow.java:12)
at JavaImages.Ja­vaShow.main(Ja­vaShow.java:20)

 
Odpovědět 30.11.2014 13:29
Avatar
Jakub Stacho:

Mam tiez taky isty problem ako chlapik v poslednom prispevku. Obrazok mam uložený pri triedach v ktorých pracuuem s nim. Ale nejde mi to.

 
Odpovědět 27. března 21:54
Avatar
B42P6
Člen
Avatar
Odpovídá na Jakub Stacho
B42P6:

Ahoj. Skontroluj si názov obrázku s názvom ktorý máš v zdrojáku. Názov obrázku v zdrojovom kóde musíš napísať aj vrátane prípony (.png, .jpg, ...). ;)

Odpovědět 28. března 0:02
'long long long' is too long for GCC
Avatar
Odpovídá na B42P6
Jakub Stacho:

Presne tak to mam :

ImageIcon ii = new ImageIcon(this­.getClass().get­Resource("obra­zok.jpg"));

obrazok = ii.getImage();

Editováno 28. března 10:54
 
Odpovědět 28. března 10:53
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 11. Zobrazit vše