Tananyag‎ > ‎Objektumorientáció‎ > ‎

Grafikus felületek II.

A JPanel
A panel jó. Olcsó, könnyű előállítani, és jó a hőszigetelése. De vajon milyen szolgálatot tesz a Java nyelvben?
Az alábbiakban csakis a javax.swing csomag JPanel nevű osztályának ügyes-bajos dolgaival fogunk foglalkozni. Az osztály egy olyan tároló, amely komponens módjára más komponensekbe illeszthető. Általánosan: mindent hozzá lehet adni, amit a JFrame-hez (előző lecke), de őt magát is hozzá lehet adni egy másik tárolóhoz. Ezáltal sokrétűbb felületeket hozhatunk létre a Java(x) eszközeivel. Azonban most sokkal inkább érdekes, hogy rajzvászonként is használhatjuk, megfelelő módosításokkal.
A rajzvászon
Minden egyes komponensnek, így a JPanelnek is megvan a paintComponent(Graphics gra) tagfüggvénye. Ha ezt megfelelően módosítjuk, határtalan lehetőségek nyílnak meg előttünk. Ehhez viszont meg kell ismerkednünk a java.awt.geom osztállyal (mindenesetre először importáljuk).
Mint az előző leckében, itt is egy osztállyal kezdünk, amely legyen a JPanel gyermeke! Egyelőre ebben az osztályban csak két dologgal foglalkozzunk: a konstruktorral és a már említett paintComponent(Graphics gra) tagfüggvénnyel!
public class CanvasPanel extends JPanel{
    public CanvasPanel(){
        
    }
    .
    .
    .
    public void paintComponent(Graphics gra){
    
    }
}
Alakítsuk a konstruktort kedvünk szerint! Döntsük el, milyen paraméterekre van szükség a JPanel elkészítéséhez. Ajánlott hozzáadni az alábbi három sort:
setMinimumSize(new Dimension(szelesseg, hosszusag));
setMaximumSize(new Dimension(szelesseg, hosszusag));
setPreferredSize(new Dimension(szelesseg, hosszusag));
Ha ezt nem tesszük meg, akkor kizárólag a BorderLayout fogja helyes méretre állítani a JPanelünket.
Fontos megjegyezni, hogy az origó a Panel bal felső sarka, az y koordináta lefelé, az x- pedig jobbra nő.
Ahhoz, hogy rajzolni tudjunk, a paintComponent függvényt kell felülírni. Először érdemes meghívni a szuperosztály paintComponentjét a gra nevű Graphics objektummal. Ezután a gra nevű objektumot kell kikényszeríteni Graphics2D-vé (legyen gra2D), hogy az összetett grafikus műveleteket is kezelni tudja. Ilyenek a
gra2D.draw(Shape shape): megrajzolja az alakzat körvonalát
gra2D.fill(Shape shape): kitölti az alakzatot az aktuális színnel
gra2D.setColor(new Color(255,0,0)): beállítja a színt. Érdemes megfigyelni a Color objektumot, melynek három paramétere a piros, a zöld és a kék komponens. Léteznek statikus mezői, például a Color.WHITE
gra2D.setStroke(new BasicStroke(3)): beállítja a vonalvastagságot. A BasicStroke osztály példányát várja, melynek konstruktora pedig egy egész vonalvastagságot (pixelben)
gra2D.setFont(Font font): Betűtípust állít. A Font osztályról bővebben itt.
gra2D.drawString(String str, int x, int y): kiírja a megadott Stringet a megadott koordinátákra.
gra2D.drawImage(BufferedImage image, int x, int y, ImageObserver io): Kirajzolja a megadott képet a megadott koordinátákra. Képet beolvasni a java.io, a java.awt.image és a javax.imageio osztályokkal lehet.
Érdemes hozzáadni az alábbi három sort a függvényhez. Ettől kevésbé lesznek töredezettek az alakzatok:
RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
gr.setRenderingHints(rh);
Most ejtsünk szót azokról a bizonyos alakzatokról!
Az alakzatok
A kirajzolható alakzatok a java.awt.geom csomag elemei. A legtöbbnek (úgynevezett téglalapszerű alakzatoknak) van egy pár közös tulajdonságuk, melyekről érdemes szót ejteni:
Két koordinátájuk van: a bennfoglaló téglalap bal felső sarkának x és y koordinátája. Állíthatóak és lekérdezhetőek a .getX(), .getY().setX(double x), .setY(double y) példánytagfüggvényekkel.
Van egy szélességük és egy hosszúságuk, melyek a bennfoglaló téglalap oldalhosszai. Állíthatóak és lekérdezhetőek a .getWidth().getHeight().setWidth(double w),  
.setHeight(double h) példánytagfüggvényekkel.
Van olyan tagfüggvényük, mely megállapítja, hogy egy pont benne van-e az alakzatban: 
.contains(Pont2D p)
Konstruktoruk paraméterei zömmel ugyanazok: az első négy rendre x, y, szélesség, magasság, utána pedig egyéb módosító tényezők. A téglalapszerű alakzatokról bővebben itt.
Fontos még megemlíteni a Line2D.Double(double x1, double y1, double x2, double y2) osztályt, amely egy vonal az első két koordináta és az utolsó két koordináta között.
Végül a ráadás: az egér!
Az egér
Újabb két eseményfigyelőt veszünk górcső alá: ez a MouseListener és a MouseMotionListener (java.awt.event). Implementáljuk az osztályunkban, majd gépeljük be az (összesen) öt eseménykezelő metódust!
public void mouseEntered(MouseEvent evt): Akkor hívódik meg, ha az egérmutató belép a figyelt alakzatba.
public void mouseExited(MouseEvent evt): Akkor hívódik meg, ha az egérmutató kilép a figyelt alakzatból.
public void mousePressed(MouseEvent evt): Az egérgomb megnyomásakor hívódik meg, ha a figyelt terület fókuszban van
public void mouseReleased(MouseEvent evt): Az egérgomb felengedésekor hívódik meg, ha a figyelt terület fókuszban van
public void mouseClicked(MouseEvent evt): Az egérgombbal való kattintáskor hívódik meg, ha a figyelt terület fókuszban van
public void mouseDragged(MouseEvent evt): Meghívódik, akárhányszor lenyomott egérgombbal mozdul meg az egér, amennyiben a figyelt terület fókuszban van.
public void mouseMoved(MouseEvent evt): Meghívódik, akárhányszor felengedett egérgombbal mozdul meg az egér, amennyiben a figyelt terület fókuszban van.
Ahhoz, hogy a panelünk fókuszba kerüljön, a konstruktorhoz kell adni két sort, az eseményfigyelő-hozzáadó metódusokat:
addMouseListener(this);
addMouseMotionListener(this);
Az egéreseménynek nagyon hasznos függvényei is vannak, például
evt.getX(): visszaadja az egérmutató x koordinátáját
evt.getX(): visszaadja az egérmutató x koordinátáját
evt.getButton(): visszaad egy intet, amit egy statikus mezővel összehasonlítva megtudhatjuk, melyik gombot nyomták le. (Pl.: evt.getButton()==MouseEvent.BUTTON1)
Most, hogy az egér eseményeit is tudjuk kezelni, már csak egy kis akaraterő választ el minket attól, hogy kis kétdimenziós játékokat készítsünk. Ugyan ez csak egy kis áttekintés volt a Java grafikus és interaktív lehetőségei fölött, de remélem, hogy irányt mutattam annak, aki ilyesmin töri a fejét. Köszönöm a lehetőséget az oldal tulajdonosának, Hornák Bencének!
Comments