Nhập môn Java 2D | VnCoding

Đây tutorial về Java 2D. Chúng ta sẽ cùng tìm hiểu kiến thức cơ bản lập trình Java 2D. Các hình ảnh trong bài viết này được tại đây.

Vector graphics

Có 2 đồ họa máy tính khác nhau: vector và graphics. Raster (bitmap) graphics mô tả ảnh như 1 bộ các điểm ảnh (pixel). Vector graphics là việc sử dụng hình học nguyên thủy như: điểm, đường thẳng, đường cong hoặc đa giác để mô tả hình ảnh. Các hình học nguyên thủy này được tạo bởi các công thức toán học.
Cả 2 loại đồ họa raster và vector đều có ưu và nhược điểm. Ưu điểm của vector graphics là:
– Kích thước nhỏ hơn
– Khả năng phóng to vô hạn
– Việc di chuyển, scale, điền dữ liệu hoặc xoay ảnh không làm giảm chất lượng của image.

Java 2D API cung cấp các tool để làm việc với cả vector và raster graphics.

Java 2D API

Java 2D API là API để vẽ đồ họa 2 chiều sử dụng ngôn ngữ Java.
Java 2D API cung cấp chức năng sau:
– Mô hình render đồng nhất cho các thiết bị hiển thị và máy in.
– Detect điểm trên hình vẽ, text và image.
– Mô hình kết hợp
– Support màu
– Kiểm soát chất lượng của render

Java 2D API cải tiến khả năng về graphics, text và image của Abstract Windowing Toolkit (AWT). AWT là bộ tool đầu tiên giành cho việc tạo User Interface (UI) và graphics trong Java. Vì mục đích tương thích, Java 2D là công cụ AWT.
Java 2D là công nghệ mạnh mẽ. Nó có thể được sử dụng để tạo rich UI, game, animation, ứng dụng multimedia và hàng loạt các hiệu ứng đặc biệt khác.

Cơ chế paint

Code paint tùy chỉnh nên đặt trong phương thức paintComponent(). Phương thức được gọi khi vẽ. Hệ thống con paint gọi phương thức paint() đầu tiên. Phương thức này gọi 3 phương thức sau:
– paintComponent()
– paintBorder()
– paintChildren()

Trong trường hợp cụ thể, chúng ta có thể muốn override phương thức paintBorder() hoặc paintChildren(). Trong hầu hết các trường hợp, chúng ta override phương thức paintComponent().

Object Graphics

Tham số duy nhất của paintComponent là 1 object Graphics. Nó cho biết số lượng phương thức vẽ hình 2D và lấy thông tin về môi trường graphics của ứng dụng. Class ‘Graphics2D’ kế thừa class ‘Graphics’ để cung cấp kiểm soát hình học tinh vi hơn, chuyển hệ tọa độ, quản lý màu và layout text.

Object ‘Graphics’ được khởi tạo trước khi nó được truyền vào phương thức paintComponent() và sau đó nó được chuyển đến các phương thức paintBorder() và paintChildren(). Việc tái sử dụng cải tiến performance nhưng nó dẫn đến problem nếu code painting thay đổi vĩnh viễn trạng thái của object ‘Graphics’. Do đó, chúng ta phải hoặc là khôi phục setting ban đầu hoặc làm việc với bản copy của object ‘Graphics’. Bản copy được tạo với phương thức create() của class ‘Graphics’. Nó phải được giải phóng (release) với phương thức dispose().

Trong thực tế, bản copy của object Graphics’ không cần được tạo nếu chúng ta set thuộc tính sau: font, color, render hints. Về các đặc tính khác (đặc biệt là hoạt động clip, hỗn hợp và biến đổi ), chúng ta phải tạo bản copy của object ‘Graphics’.

Ví dụ về Java 2D

Ví dụ minh họa tạo Java 2D application

package net.vncoding;

import java.awt.EventQueue;
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;
        g2d.drawString("Java 2D", 50, 50);
    }

    @Override
    public void paintComponent(Graphics g) {

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

public class BasicEx extends JFrame {

    public BasicEx() {

        initUI();
    }

    private void initUI() {

        add(new Surface());

        setTitle("Simple Java 2D example");
        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {

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

Giải thích:
Chúng ta vẽ text trên JPanel.

class Surface extends JPanel {
...
}

Chúng ta tạo class ‘Surface’. Class này là drawing panel. Nó kế thừa từ ‘JPanel’.

Graphics2D g2d = (Graphics2D) g;

Class ‘Graphics2D’ là class cơ bản cho việc redering graphics trong Java 2D. Nó mô tả số lượng device một cách chung chung. Nó mở rộng object ‘Graphics’ cũ. Việc ép kiểu (castin) là cần thiết để lấy quyền truy cập tới tất cả các function cải tiến.

g2d.drawString("Java 2D", 50, 50);

Vẽ chuỗi text trên panel với phương thức drawString().

@Override
public void paintComponent(Graphics g) {

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

Việc tùy biến vẽ được thực hiện bên trong phương thức paintComponent(). Phương thức super.paintComponent() gọi phương thức của parent class. Nó thực hiện vài công việc để chuẩn bị component cho việc vẽ. Phương thức doDrawing() làm nhiệm vụ vẽ

private void initUI() {
...
}

Phương thức initUI() khởi tạo UI của ứng dụng.

add(new Surface());

Surface được lưu vào container JFrame.

EventQueue.invokeLater(new Runnable() {

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

Chúng ta tạo object của class BasicEx và hiển thị nó trên màn hình. Phương thức invokeLater() đặt ứng dụng vào hàng đợi Swing (Swing Event Queue). Nó được sử dụng để đảm bảo tất cả việc update IU là an toàn

Kết quả:
Java 2D - Simple application