Java 2D – Shape and fill

Trong bài này, chúng ta tìm hiểu sâu hơn về shape và các fill color cho các shape.

Basic shape

Ví dụ này sẽ 1 shape cơ bản.

BasicShapes.java

package net.vncoding;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;


class Surface extends JPanel {
    
    private void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setPaint(new Color(150, 150, 150));

        RenderingHints rh = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        rh.put(RenderingHints.KEY_RENDERING,
               RenderingHints.VALUE_RENDER_QUALITY);

        g2d.setRenderingHints(rh);

        g2d.fillRect(30, 20, 50, 50);
        g2d.fillRect(120, 20, 90, 60);
        g2d.fillRoundRect(250, 20, 70, 60, 25, 25);

        g2d.fill(new Ellipse2D.Double(10, 100, 80, 100));
        g2d.fillArc(120, 130, 110, 100, 5, 150);
        g2d.fillOval(270, 130, 50, 50);
   } 

    @Override
    public void paintComponent(Graphics g) {
        
        super.paintComponent(g);
        doDrawing(g);
    }    
}

public class BasicShapesEx extends JFrame {

    public BasicShapesEx() {

        initUI();
    }
    
    private void initUI() {
        
        add(new Surface());
        
        setTitle("Basic shapes");
        setSize(350, 250);
        setLocationRelativeTo(null);        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
        
            @Override
            public void run() {
                BasicShapesEx ex = new BasicShapesEx();
                ex.setVisible(true);
            }
        });
    }
}

Giải thích:
Trong ví dụ này, chúng ta vẽ 6 hình vẽ cơ bản: hình vuông, hình chữ nhật, hình chữ nhật góc bo tròn, elip, hình vòng cung và hình tròn.

g2d.setPaint(new Color(150, 150, 150));

Các hình được vẽ trên blackground màu xám.

g2d.fillRect(20, 20, 50, 50);
g2d.fillRect(120, 20, 90, 60);

Phương thức fillRect() được sử dụng để vẽ và hình chữ nhật và hình vuông. 2 tham số đầu là tọa độ x, y của hình vẽ. 2 tham số cuối là chiều rộng và chiều cao của hình vẽ.

g2d.fillRoundRect(250, 20, 70, 60, 25, 25);

Chúng ta vẽ hình chữ nhật bo tròn góc. 2 tham số cuối là đường kính theo chiều ngang và chiều dọc của đường cong tại 4 góc.

g2d.fill(new Ellipse2D.Double(10, 100, 80, 100));

Ellipse2D.Double(10, 100, 80, 100) khởi tạo đối tượng elip. 2 tham số đầu là độ cao, chiều rộng. 2 tham số cuối là tạo độ x, y góc trái hình chữ nhật chưa elip.
Phương thức fill() vẽ hình elip.

g2d.fillArc(120, 130, 110, 100, 5, 150);

Phương thức fillArc() fill hình tròn hoặc elip bao quanh hình chữ nhật. Cung tròn là 1 phần của hình tròn.
2 tham số đầu là tọa độ x, y của hình chữ nhật bao quanh cung tròn
2 tham số tiếp theo là chiều rộng và chiều cao của cung tròn
2 tham số cuối là góc bắt đầu và góc kết thúc của đường cong. (giống với quy ước đường tròn lượng giác trong toán học)

g2d.fillOval(270, 130, 50, 50);

Hình tròn được vẽ bởi phương thức fillOval()
2 tham số đầu là tọa độ x, y góc trái của hình oval
2 tham số cuối là chiều rộng và chiều cao của hình oval

Kết quả:

Java 2D - Basic Shape
Java 2D – Basic Shape

General path

Hình phức tạp là tập hợp của General Path. Nó mô tả 1 hình học mà gồm có đường thẳng, đường cong Bezier bậc 2 và bậc 3.
Trong ví dụ này, chúng ta vẽ hình ngôi sao.

StarEx.java

package net.vncoding;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel {

    private final double points[][] = { 
        { 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 }, 
        { 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 }, 
        { 40, 190 }, { 50, 125 }, { 0, 85 } 
    };
    
    private void doDrawing(Graphics g) {
        
        Graphics2D g2d = (Graphics2D) g.create();

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
                             RenderingHints.VALUE_RENDER_QUALITY);

        g2d.setPaint(Color.gray);
        g2d.translate(25, 5);

        GeneralPath star = new GeneralPath();

        star.moveTo(points[0][0], points[0][1]);

        for (int k = 1; k < points.length; k++)
            star.lineTo(points[k][0], points[k][1]);

        star.closePath();
        g2d.fill(star);        
        
        g2d.dispose();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        doDrawing(g);
    }
}

public class StarEx extends JFrame {
    
    public StarEx() {

        initUI();
    }    
    
    private void initUI() {
        
        add(new Surface());
        
        setTitle("Star");
        setSize(350, 250);
        setLocationRelativeTo(null);           
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                StarEx ex = new StarEx();
                ex.setVisible(true);
            }
        });
    }    
}

Giải thích:
Chúng ta tạo hình ngôi sao từ chuỗi các điểm.

private final double points[][] = { 
    { 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 }, 
    { 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 }, 
    { 40, 190 }, { 50, 125 }, { 0, 85 } 
};

Đây là các cặp tọa độ điểm (x, y)

GeneralPath star = new GeneralPath();

Tạo 1 object của class GeneralPath.

star.moveTo(points[0][0], points[0][1]);

Chúng ta di chuyển tới hệ trục tọa độ ban đầu của GeneralPath.

for (int k = 1; k < points.length; k++)
    star.lineTo(points[k][0], points[k][1]);

Nối tất cả các điểm thành đường ngôi sao.

star.closePath();
g2d.fill(star);

Dừng việc vẽ và fill đầy hình ngôi sao.

Kết quả:

Java 2D - Vẽ hình ngôi sao
Java 2D – Vẽ hình ngôi sao

Area

Một cách khác đê tạo ra các hình phức tạp là tổ hợp area. Area lưu và thao xử lý mô tả độ phân giải độc lập của area khép kín trong không gian 2 chiều. Nó có thể được xử lý bởi phép toán cộng, trừ, giao nhau,…

AreasEx.java

package net.vncoding;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel {
        
    public void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        
        RenderingHints rh = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        rh.put(RenderingHints.KEY_RENDERING,
               RenderingHints.VALUE_RENDER_QUALITY);    
        g2d.setRenderingHints(rh);

        g2d.setPaint(Color.gray);
        
        Area a1 = new Area(new Rectangle2D.Double(20, 20, 100, 100));
        Area a2 = new Area(new Ellipse2D.Double(50, 50, 100, 100));
        
        a1.subtract(a2);
        g2d.fill(a1);
        
        Area a3 = new Area(new Rectangle2D.Double(150, 20, 100, 100));
        Area a4 = new Area(new Ellipse2D.Double(150, 20, 100, 100));        
        
        a3.subtract(a4);
        g2d.fill(a3);
        
        Area a5 = new Area(new Rectangle2D.Double(280, 20, 100, 100));
        Area a6 = new Area(new Ellipse2D.Double(320, 40, 100, 100));        
        
        a5.add(a6);
        g2d.fill(a5);        
    }

    @Override
    public void paintComponent(Graphics g) {
                
        super.paintComponent(g);
        doDrawing(g);
    }           
}

public class AreasEx extends JFrame {

    public AreasEx() {

        initUI();
    }

    private void initUI() {
        
        add(new Surface());
        
        setTitle("Areas");
        setSize(450, 200);
        setLocationRelativeTo(null);        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                AreasEx ex = new AreasEx();
                ex.setVisible(true);
            }
        });
    }
}

Giải thích:
Ví dụ tạo ra 3 hình khác nhau bằng cách tổ hợp các area.

Area a1 = new Area(new Rectangle2D.Double(20, 20, 100, 100));
Area a2 = new Area(new Ellipse2D.Double(50, 50, 100, 100));

a1.subtract(a2);
g2d.fill(a1);

Đoạn code này tạo ra hình bằng cách lấy hình chữ nhật “trừ” đi hình elip

Area a5 = new Area(new Rectangle2D.Double(280, 20, 100, 100));
Area a6 = new Area(new Ellipse2D.Double(320, 40, 100, 100));        

a5.add(a6);
g2d.fill(a5); 

Đoạn code này tạo ra hình bằng cách “cộng” hình chữ nhật và hình elip.

Kết quả:

Java 2D - Vẽ hình phức tạp
Java 2D – Vẽ hình phức tạp

Color

Class color được sử dụng để làm việc với màu trong Java 2D. Để fill màu cho hình chữ nhật, chúng ta sử dụng phương thức fillRect().

ColoursEx.java

package net.vncoding;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel {
        
    public void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(new Color(125, 167, 116));
        g2d.fillRect(10, 10, 90, 60);

        g2d.setColor(new Color(42, 179, 231));
        g2d.fillRect(130, 10, 90, 60);

        g2d.setColor(new Color(70, 67, 123));
        g2d.fillRect(250, 10, 90, 60);

        g2d.setColor(new Color(130, 100, 84));
        g2d.fillRect(10, 100, 90, 60);

        g2d.setColor(new Color(252, 211, 61));
        g2d.fillRect(130, 100, 90, 60);

        g2d.setColor(new Color(241, 98, 69));
        g2d.fillRect(250, 100, 90, 60);

        g2d.setColor(new Color(217, 146, 54));
        g2d.fillRect(10, 190, 90, 60);

        g2d.setColor(new Color(63, 121, 186));
        g2d.fillRect(130, 190, 90, 60);

        g2d.setColor(new Color(31, 21, 1));
        g2d.fillRect(250, 190, 90, 60);
    }

    @Override
    public void paintComponent(Graphics g) {
                
        super.paintComponent(g);
        doDrawing(g);
    }           
}

public class ColoursEx extends JFrame {

    public ColoursEx() {

        initUI();
    }

    private void initUI() {
        
        add(new Surface());
        
        setTitle("Colours");
        setSize(360, 300);
        setLocationRelativeTo(null);        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ColoursEx ex = new ColoursEx();
                ex.setVisible(true);
            }
        });
    }
}

Trong ví dụ này, chúng ta vẽ 9 hình chữ nhật với màu sắc khác nhau.

Graphics2D g2d = (Graphics2D) g;

Không cần tạo bản copy của class Graphics2D hoặc reset giá trị khi chúng ta change đặc tính màu của ngữ cảnh đồ học (graphics context)

g2d.setColor(new Color(125, 167, 116));

Màu mới được tạo với class Color. Tham số của hàm tạo là mày đỏ, xanh green, blue. Phương thức setColor() set màu cho hình vẽ. Tất cả chuỗi xử lý đồ họa sau đó sẽ sử dụng giá trị màu này.

g2d.fillRect(10, 15, 90, 60);

Để fill hình chữ nhật với màu, chúng ta sử dụng phương thức fillRect()

Java 2D - Fill màu cho hình vẽ
Java 2D – Fill màu cho hình vẽ

Gradient

Trong đồ hoạ máy tính, gradient là một pha trộn mịn của sắc thái từ ánh sáng đến tối hoặc từ một màu khác. Trong các chương trình vẽ 2D và các chương trình vẽ, các gradient được sử dụng để tạo ra nhiều màu sắc và hiệu ứng đặc biệt cũng như để mô phỏng các bóng đèn và bóng.

GradientsEx.java

package net.vncoding;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel {
    
    private void doDrawing(Graphics g) {
        
        Graphics2D g2d = (Graphics2D) g.create();

        GradientPaint gp1 = new GradientPaint(5, 5, 
            Color.red, 20, 20, Color.black, true);

        g2d.setPaint(gp1);
        g2d.fillRect(20, 20, 300, 40);

        GradientPaint gp2 = new GradientPaint(5, 25, 
            Color.yellow, 20, 2, Color.black, true);

        g2d.setPaint(gp2);
        g2d.fillRect(20, 80, 300, 40);

        GradientPaint gp3 = new GradientPaint(5, 25, 
            Color.green, 2, 2, Color.black, true);

        g2d.setPaint(gp3);
        g2d.fillRect(20, 140, 300, 40);

        GradientPaint gp4 = new GradientPaint(25, 25, 
            Color.blue, 15, 25, Color.black, true);

        g2d.setPaint(gp4);
        g2d.fillRect(20, 200, 300, 40);

        GradientPaint gp5 = new GradientPaint(0, 0, 
             Color.orange, 0, 20, Color.black, true);

        g2d.setPaint(gp5);
        g2d.fillRect(20, 260, 300, 40);   
        
        g2d.dispose();
    }

    @Override
    public void paintComponent(Graphics g) {
        
        super.paintComponent(g);
        doDrawing(g);
    }
}

public class GradientsEx extends JFrame {
    
    public GradientsEx() {

        initUI();
    }    
    
    private void initUI() {
        
        add(new Surface());
        
        setTitle("Gradients");
        setSize(350, 350);
        setLocationRelativeTo(null);            
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
        
            @Override
            public void run() {
                GradientsEx ex = new GradientsEx();
                ex.setVisible(true);
            }
        });
    }    
}

Giải thích:
Trong ví dụ, vẽ 5 hình chữ nhật với gradient.

GradientPaint gp4 = new GradientPaint(25, 25, 
    Color.blue, 15, 25, Color.black, true);

Để làm việc với gradient, chúng ta sử dụng class GradientPaint. Việc thao tác giá trị màu và các điểm bắt đầu và kết thúc, chúng ta thu được kết quả khác nhau.

g2d.setPaint(gp4);

Active gradien bằng việc gọi phương thức setPaint()

Kết quả:

Java 2D - Gradient
Java 2D – Gradient

Textures

Texture là ảnh bitmap được apply vào hình vẽ. Để làm việc với texture trong Java 2D, chúng ta sử dụng class TexturePaint. Texture được apply với phương thức setPaint().

TexturesEx.java

package net.vncoding;

import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel {

    private BufferedImage slate;
    private BufferedImage java;
    private BufferedImage pane;
    private TexturePaint slatetp;
    private TexturePaint javatp;
    private TexturePaint panetp;

    public Surface() {

        loadImages();
    }

    private void loadImages() {

        try {

            slate = ImageIO.read(new File("slate.png"));
            java = ImageIO.read(new File("java.png"));
            pane = ImageIO.read(new File("pane.png"));

        } catch (IOException ex) {

            Logger.getLogger(Surface.class.getName()).log(
                    Level.SEVERE, null, ex);
        }
    }

    private void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g.create();

        slatetp = new TexturePaint(slate, new Rectangle(0, 0, 90, 60));
        javatp = new TexturePaint(java, new Rectangle(0, 0, 90, 60));
        panetp = new TexturePaint(pane, new Rectangle(0, 0, 90, 60));

        g2d.setPaint(slatetp);
        g2d.fillRect(10, 15, 90, 60);

        g2d.setPaint(javatp);
        g2d.fillRect(130, 15, 90, 60);

        g2d.setPaint(panetp);
        g2d.fillRect(250, 15, 90, 60);
        
        g2d.dispose();
    }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        doDrawing(g);
    }
}

public class TexturesEx extends JFrame {

    public TexturesEx() {

        initUI();
    }
    
    private void initUI() {
        
        add(new Surface());

        setTitle("Textures");
        setSize(360, 120);
        setLocationRelativeTo(null);        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
        
            @Override
            public void run() {
                TexturesEx ex = new TexturesEx();
                ex.setVisible(true);
            }
        });
    }
}

Giải thích:
Trong đoạn code này, chúng ta vẽ 3 hình chữ nhật với texture khác nhau.

slate = ImageIO.read(new File("slate.png"));

Sử dụng class ImageIO, chúng ta load ảnh vào bộ đệm.

slatetp = new TexturePaint(slate, new Rectangle(0, 0, 90, 60));

Chúng ta tạo class TexturePaint bên ngoài bộ đệm ảnh.

g2d.setPaint(slatetp);
g2d.fillRect(10, 15, 90, 60);

Chúng ta fill hình chữ nhật với texture.

Kết quả:

Java 2D - Vẽ hình với texture
Java 2D – Vẽ hình với texture

Be the first to comment

Leave a Reply