[[oktatas:programozás:java|< Java]] ====== Java Swing Grafika ====== * **Szerző:** Sallai András * Copyright (c) 2011, Sallai András * Szerkesztve: 2011, 2013, 2014, 2015, 2021 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== A rajzolásról ===== A rajzoló alrendszer először a paint() metódust hívja, ha rajzolni kell. A paint() metódus a következő három metódust hívja: * paintComponent() * paintBorder() * paintChildren() Rajzolhatunk mind a négy metódussal. Mi most a paint() metódussal kezdjük. Látni fogjuk, hogy rajzolni többféle képen, szinten minden komponensre rajzolhatunk. Ez utóbbi lehetőség nem szokványos dolog. Sok programozói eszköztár nem teszi lehetővé minden komponensre való rajzolást. ==== Rendszer által kiváltott rajzolás ==== Rendszerint a következő esetekben következik be: * megjelenik egy komponens * a komponens átméreteződik * a komponens változik (például láthatóvá válik egy eddig kitakart rész) A fenti esetekben végrehajtódik a paint() metódus. ===== Rajzolás a keretre ===== Elsőként az ablakkeretre fogunk rajzolni. Elkészítünk egy ablakkeretet, majd a paint() metódussal rajzolunk rá. A rajzolómetódus előtt meg kell adni, hogy milyen színnel szeretnénk rajzolni. A rajzolás során x, y koordinátákat adunk, a rajz elhelyezéséhez. Az x a vízszintes, az y a függőleges koordináta. A kezdőpont a bal felső sarok. Vagyis a bal felső sarok a 0,0 origó. {{:oktatas:programozás:java:koordinatarendszer.png|}} import javax.swing.JFrame; import java.awt.Graphics; import java.awt.Color; class Program01 extends JFrame { Program01() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); } public static void main(String args[]) { new Program01(); } @Override public void paint(Graphics g) { g.setColor(Color.BLUE); g.fillRect(30, 30, 100, 30); } } Ügyeljünk arra, hogy ha keretre rajzolunk, akkor a vízszintes 0 az ablak tetején van, és nem a címsornál kezdődik. Elemezzük a g.fillRect(30, 30, 100, 30); metódust. A metódus egy téglalapot rajzol az ablakkeretre. Az első két koordináta x, y. A másik kettő, szélesség és magasság. Ezek után általánosan így írhatjuk fel: g.fillRect(x, y, szélesség, magasság); Fentebb már láttuk, hogy az x a vízszintes koordináta, az y a függőleges. Adott színek: * Color.BLACK * Color.BLUE * Color.CYAN * Color.DARK_GRAY * Color.GRAY * Color.GREEN * Color.LIGHT_GRAY * Color.MAGENTA * Color.ORANGE * Color.PINK * Color.RED * Color.WHITE * Color.YELLOW Saját szín megadása, például királykék: g.setColor(new Color(0, 0, 80)); A színt RGB kódolással keverjük ki. Néhány rajzolómetódus: * drawLine(int x1, int y1, int x2, int y2) * drawOval(int x, int y, int width, int height) * drawRect(int x, int y, int width, int height) * drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) * drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) * draw3DRect(int x, int y, int width, int height, boolean raised) * drawString(String str, int x, int y) * fillOval(int x, int y, int width, int height) * fillRect(int x, int y, int width, int height) * fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) * fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) * fill3DRect(int x, int y, int width, int height, boolean raised) ===== Rajzolás keretre és komponenshasználat ===== Ha AWT vagy Swing komponenseket is használunk, akkor a grafika nem jelenik meg. A super.paint(g) meghívásával, viszont megrajzolódik. import javax.swing.JFrame; import javax.swing.JButton; import java.awt.Graphics; import java.awt.Color; class Program01 extends JFrame { JButton button = new JButton("Kattints"); Program01() { button.setLocation(25, 30); button.setSize(100, 30); setLayout(null); add(button); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); } public static void main(String args[]) { new Program01(); } @Override public void paint(Graphics g) { super.paint(g); g.setColor(Color.BLUE); g.fillRect(150, 30, 100, 30); } } ===== Rajzolás JComponentre ===== A JComponent osztályból készíthetünk újabb komponenseket. import javax.swing.JFrame; import javax.swing.JComponent; import java.awt.Graphics; import java.awt.Color; class Program01 extends JFrame { SajatKomponens sk = new SajatKomponens(); Program01() { this.add(sk); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(400, 300); this.setVisible(true); } public static void main(String args[]) { new Program01(); } } class SajatKomponens extends JComponent { public void paint(Graphics g) { g.setColor(Color.BLUE); g.fillRect(30, 30, 100, 30); } } ===== A paintComponent() ===== Ha valamilyen komponensre rajzolunk, akkor felülírhajtuk a paintComponent() metódust is: import javax.swing.JFrame; import javax.swing.JComponent; import java.awt.Graphics; import java.awt.Color; class Program01 extends JFrame { SajatKomponens sk = new SajatKomponens(); Program01() { this.add(sk); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(400, 300); this.setVisible(true); } public static void main(String args[]) { new Program01(); } } class SajatKomponens extends JComponent { @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.BLUE); g.fillRect(30, 30, 100, 30); } } ===== Ablak a panelosztályban ===== A JPanel osztályból örökítem a főosztályt, majd egy JFrame ablakot hozok létre az osztályon belül és ehhez hozzáadom a főosztályt konstruktorként meghívva. import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; public class Program2 extends JPanel { public static void main(String[] a) { JFrame ablak = new JFrame(); ablak.setSize(400, 400); ablak.add(new Program2()); ablak.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ablak.setVisible(true); } public void paint(Graphics g) { g.setColor (Color.red); /* Az utolsó két paraméter fokban van megadva. A fokokat ha óraszámlaphoz hasonlítom, akkor a kezdés 3 óránál van. x, y, szélesség, magasság, kezdés_fok, hozzáadott_fok */ g.drawArc (5, 15, 50, 75, 25, 165); } } ===== Rajzolás nyomógombra ===== import javax.swing.JFrame; import javax.swing.JButton; import java.awt.Graphics; import java.awt.Color; class Program04 extends JFrame { SajatGomb gomb = new SajatGomb(); Program04() { gomb.setLocation(25, 25); gomb.setSize(100, 30); this.setLayout(null); this.add(gomb); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(400, 300); this.setVisible(true); } public static void main(String args[]) { new Program04(); } } class SajatGomb extends JButton { @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.BLUE); g.fillRect(5, 5, 10, 10); } } Ha nem hívjuk meg a super.paintComponent(g) utasítást, akkor nem rajzolódik ki minden részlet, de így járunk akkor is, ha paintComponent(Graphics g) helyett csak a paint(Graphics g) metódust írjuk át. ===== Csak rajz ===== import javax.swing.*; import java.awt.*; class Program extends JFrame { Program() { getContentPane().add(new SajatKomponens()); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 600); setVisible(true); } public static void main(String args[]) { new Program(); } public class SajatKomponens extends JComponent { public void paint(Graphics g) { g.setColor(Color.blue); g.drawRect(10, 10, 50, 50); } } } ===== Saját panel osztály ===== import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; public class Program2 { SajatPanel panel1; JFrame ablak; Program2() { panel1 = new SajatPanel(); ablak = new JFrame(); ablak.setSize(400, 400); ablak.add(panel1); ablak.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ablak.setVisible(true); } public static void main(String[] a) { new Program2(); } class SajatPanel extends JPanel { public void paint(Graphics g) { g.setColor (Color.red); g.drawArc (5, 15, 50, 75, 25, 165); } } } ===== Két színes panel ===== A következő nem éppen grafika, de a látvány inkább közel áll ahhoz. import javax.swing.*; import java.awt.*; class Program extends JFrame { JPanel panel1; JPanel panel2; Program() { panel1 = new JPanel(); panel2 = new JPanel(); panel1.setSize(200, 200); panel1.setLocation(50, 50); panel1.setBackground(Color.blue); panel2.setSize(200, 200); panel2.setLocation(50, 280); panel2.setBackground(Color.red); this.setLayout(null); this.add(panel1); this.add(panel2); this.setSize(800, 600); this.setLocationRelativeTo(null); this.setVisible(true); } public static void main(String args[]) { new Program(); } } ===== Graphics2D ===== A Graphics2D osztály a Graphics osztály kiterjesztése, amely lehetővé teszi fejlettebb geometriai alakzatok, koordináta transzformációkat, színkezelést, szövegelrendezést. import javax.swing.*; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Line2D; class Program extends JFrame { Program() { getContentPane().add(new SajatKomponens()); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 600); setVisible(true); } public static void main(String args[]) { new Program(); } public class SajatKomponens extends JComponent { public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setColor(Color.blue); Line2D lin = new Line2D.Float(100, 100, 250, 260); g2.draw(lin); } } } A példából láthatjuk, hogy a Graphics2D objektumot a Graphics objektumból készítjük típuskényszerítéssel. ===== Canvas osztály ===== A Canvas osztály direkt rajzolófelületnek tervezték. import java.awt.*; import javax.swing.*; class Program extends JFrame { Canvas vaszon = new Vaszon(); Program() { add(vaszon); setSize(300, 200); setVisible(true); } class Vaszon extends Canvas { public void paint(Graphics g) { g.drawLine(10,10, 50, 50); } } public static void main(String args[]) { new Program(); } } A példában egy Canvas osztályból egy beépített osztályt készítünk. ===== Háttérszín rajzoláskor ===== Ha egy panelen megvalósítjuk a paint() metódust, akkor elveszti a háttérszínét. Ezért a paint() metódusban egy megkerülőmegoldást alkalmazunk, a komponenssel egyező nagyságú téglalapot rajzolunk: import javax.swing.*; import java.awt.*; class SajatPanel extends JPanel { SajatPanel() { setBackground(Color.blue); setBounds(100, 100, 300, 300); } public void paint(Graphics g) { g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(getForeground()); Color szin = new Color(0,0,255); g.setColor(szin); g.drawString("valami", 50, 10); } } class Program extends JFrame { SajatPanel panel; Program() { panel = new SajatPanel(); panel.setBackground(Color.blue); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(null); add(panel); setSize(800, 600); setVisible(true); } public static void main(String[] argv) { new Program(); } } Az ide vonatkozó rész: g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(getForeground()); ===== Fontbeállítás ===== A fontbeállítás egyik eszköze a Font osztály. A Font osztály konstruktorának paramétereként megadható a fontcsalád, a font stílusa és a font mérete. Font courier = new Font ("Courier", Font.PLAIN, 12); Font system = new Font ("System", Font.BOLD, 16); Font helvetica = new Font ("Helvetica", Font.BOLD, 18); g.setFont (courier); g.drawString ("Courier", 10, 30); g.setFont (system); g.drawString ("System", 10, 70); g.setFont (helvetica); g.drawString ("Helvetica", 10, 90); A következő példában lekérdezzük a font minden tulajdonságát, majd beállítjuk csak a méretét: Font eredetiFont = g.getFont(); Font ujFont = eredetiFont.deriveFont(eredetiFont.getSize() * 1.4F); g.setFont(ujFont); ===== Sokszög rajzolása ===== Sokszög rajzolására külön osztály áll rendelkezésre, a Polygon. A Polygon osztály objektumához pontokat tudunk hozzáadni. Minden pontot x, y koordinátával adunk meg. Végül a fillPolygon() metódussal rajzoljuk meg. import javax.swing.JFrame; import java.awt.Canvas; import java.awt.Graphics; import java.awt.Color; import java.awt.Polygon; class Program01 extends JFrame { RajzVaszon rajzVaszon = new RajzVaszon(); Program01() { add(rajzVaszon); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 600); setVisible(true); } public static void main(String[] args) { new Program01(); } } class RajzVaszon extends Canvas { public void paint(Graphics g) { g.setColor(Color.red); Polygon poly = new Polygon(); poly.addPoint(200, 200); poly.addPoint(250, 250); poly.addPoint(250, 300); g.fillPolygon(poly); } } A fillPolygon() metódus három paramétert is fogadhat, ahol tömbként adom át a pontok koordinátáit. A pontokat két külön tömbben adjuk meg, harmadik paraméterként a pontok száma. int xpoints[] = {30, 150, 30, 150, 30}; int ypoints[] = {30, 30, 150, 150, 30}; int npoints = 5; g.fillPolygon(xpoints, ypoints, npoints); ===== Koordináta rendszer rajzolása ===== class SajatCanvas extends java.awt.Canvas { SajatCanvas() { setSize(800, 600); } public void paint(java.awt.Graphics g) { drawHorizontalRule(g); drawVerticalRule(g); drawContent(g); } public void drawContent(java.awt.Graphics g) { //Ide rajzolunk } public void drawHorizontalRule(java.awt.Graphics g) { java.awt.Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); int width = (int) dim.getWidth(); g.drawLine(5, 5, width, 5); for(int i=5; i ===== Vonalak rajzolása ===== A következő példa vonalak rajzolását mutatja be, egérrel. import javax.swing.*; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import java.util.*; class Program01 { public static void main ( String[] args ) { JFrame paint = new JFrame (); paint.add ( new JComponent () { private ArrayList shapes = new ArrayList(); private Shape currentShape = null; { MouseAdapter mouseAdapter = new MouseAdapter () { public void mousePressed ( MouseEvent e ) { currentShape = new Line2D.Double ( e.getPoint (), e.getPoint () ); shapes.add ( currentShape ); repaint (); } public void mouseReleased ( MouseEvent e ) { currentShape = null; repaint (); } public void mouseDragged ( MouseEvent e ) { Line2D shape = ( Line2D ) currentShape; shape.setLine ( shape.getP1 (), e.getPoint () ); repaint (); } }; addMouseListener ( mouseAdapter ); addMouseMotionListener ( mouseAdapter ); } protected void paintComponent ( Graphics g ) { Graphics2D g2d = ( Graphics2D ) g; g2d.setPaint ( Color.BLACK ); for ( Shape shape : shapes ) { g2d.draw ( shape ); } } } ); paint.setSize ( 500, 500 ); paint.setLocationRelativeTo ( null ); paint.setVisible ( true ); } } ===== Kép panelon ===== A panelt mintegy kép tárolójaként használjuk a következő példában. import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.Image; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.ImageIcon; class ImagePanel extends JPanel { private Image img; ImagePanel(Image img) { this.img = img; setPreferredSize(new Dimension(200, 200)); setLayout(null); } public void paintComponent(Graphics g) { g.drawImage(img, 0, 0, null); } } class Program01 extends JFrame { ImagePanel imagePanel = new ImagePanel(new ImageIcon("kep.png").getImage()); Program01() { add(imagePanel); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); } public static void main(String[]args) { new Program01(); } } Két új osztályt is használunk, az Image és az ImageIcont. ===== Rajzolás eseménykezelőből ===== Eseménykezelőből azért különleges a rajzolás, mert ezt a paint() metódusból szoktuk végezni, ahol paraméterként megkapjunk egy java.awt.Graphics objektumot. Az eseménykezelőben viszont nincs a formális paraméterek között ilyen objektum. Ezen segít a getGraphics() metódus, amelyet a JPanel objektumon hívhatunk meg. Az alábbi példában átkonvertáljuk Graphics2D objektummá. private void jButtonMouseClicked(java.awt.event.MouseEvent evt) { Graphics2D gfx = (Graphics2D)jPanel1.getGraphics(); gfx.drawLine(0, 0, 100, 100); } A teljes példa: import javax.swing.JFrame; import javax.swing.JButton; import java.awt.Graphics; import java.awt.Color; import java.awt.event.MouseListener; import java.awt.event.MouseEvent; class Program01 extends JFrame { final static long serialVersionUID = 1; JButton button = new JButton("Kattints"); Program01() { button.setLocation(25, 30); button.setSize(100, 30); button.addMouseListener(new MouseListener(){ public void mouseExited(MouseEvent evt) { } public void mouseEntered(MouseEvent evt) { } public void mouseReleased(MouseEvent evt) { } public void mousePressed(MouseEvent evt) { } public void mouseClicked(MouseEvent evt) { buttonMouseClick(evt); } }); setLayout(null); add(button); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); } public void buttonMouseClick(MouseEvent evt) { Graphics g = getGraphics(); g.setColor(Color.BLUE); g.fillRect(150, 30, 100, 30); } public static void main(String args[]) { new Program01(); } } ===== Törlés ===== clearRect(int x, int y, int width, int height) ===== Link ===== * https://www.oracle.com/java/technologies/painting.html (2021)