簡単なグラフィックス(Graphicsクラスの基本)

2025-08-06

Swingアプリケーションで図形や画像を描画するには、java.awt.GraphicsクラスとそのサブクラスであるGraphics2Dを使用します。これらを活用することで、基本的な図形から複雑なグラフィックスまで描画できます。

Graphicsクラスの基本構造

graphicMethods

基本的な描画の流れ

  1. JComponentを継承したカスタムコンポーネントを作成
  2. paintComponent(Graphics g)メソッドをオーバーライド
  3. Graphicsオブジェクトを使用して描画処理を実装
import javax.swing.*;
import java.awt.*;

public class BasicDrawingExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("基本的な描画例");
            frame.setSize(500, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // カスタム描画コンポーネント
            JPanel drawingPanel = new JPanel() {
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);

                    // 背景色の設定
                    g.setColor(Color.WHITE);
                    g.fillRect(0, 0, getWidth(), getHeight());

                    // 図形の描画
                    g.setColor(Color.RED);
                    g.drawRect(50, 50, 100, 80); // 矩形

                    g.setColor(Color.BLUE);
                    g.fillOval(200, 50, 100, 80); // 楕円

                    g.setColor(Color.GREEN);
                    g.drawLine(50, 200, 300, 200); // 直線

                    // 文字列の描画
                    g.setColor(Color.BLACK);
                    g.setFont(new Font("Meiryo", Font.BOLD, 16));
                    g.drawString("Swingグラフィックスの基本", 50, 250);
                }
            };

            frame.add(drawingPanel);
            frame.setVisible(true);
        });
    }
}

基本図形の描画

描画メソッド一覧

メソッド説明
drawLine(x1, y1, x2, y2)直線を描画g.drawLine(10, 10, 100, 100)
drawRect(x, y, width, height)矩形を描画g.drawRect(50, 50, 100, 80)
fillRect(x, y, width, height)塗りつぶし矩形g.fillRect(50, 50, 100, 80)
drawOval(x, y, width, height)楕円を描画g.drawOval(50, 50, 100, 80)
fillOval(x, y, width, height)塗りつぶし楕円g.fillOval(50, 50, 100, 80)
drawArc(x, y, width, height, startAngle, arcAngle)円弧を描画g.drawArc(50, 50, 100, 100, 0, 90)
fillArc(x, y, width, height, startAngle, arcAngle)塗りつぶし円弧g.fillArc(50, 50, 100, 100, 0, 90)
drawPolygon(xPoints, yPoints, nPoints)多角形を描画int[] x = {100, 150, 50}; int[] y = {50, 100, 100}; g.drawPolygon(x, y, 3)
fillPolygon(xPoints, yPoints, nPoints)塗りつぶし多角形g.fillPolygon(x, y, 3)

Graphics2Dの高度な描画機能

Graphics2DGraphicsのサブクラスで、より高度な描画機能を提供します。

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class Graphics2DExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Graphics2D例");
            frame.setSize(600, 500);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = new JPanel() {
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    Graphics2D g2d = (Graphics2D)g;

                    // アンチエイリアシングの有効化
                    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                                        RenderingHints.VALUE_ANTIALIAS_ON);

                    // 背景
                    g2d.setColor(new Color(240, 240, 240));
                    g2d.fillRect(0, 0, getWidth(), getHeight());

                    // グラデーション塗りつぶし
                    GradientPaint gradient = new GradientPaint(
                        0, 0, Color.BLUE, 
                        getWidth(), getHeight(), Color.CYAN);
                    g2d.setPaint(gradient);
                    g2d.fill(new RoundRectangle2D.Double(50, 50, 200, 150, 30, 30));

                    // 太い線とストローク
                    g2d.setPaint(Color.RED);
                    g2d.setStroke(new BasicStroke(5));
                    g2d.draw(new Ellipse2D.Double(300, 50, 200, 150));

                    // 回転変換
                    g2d.rotate(Math.toRadians(45), 400, 300);
                    g2d.setColor(new Color(0, 100, 0, 128)); // 半透明
                    g2d.fill(new Rectangle2D.Double(350, 250, 100, 100));
                    g2d.rotate(Math.toRadians(-45), 400, 300); // 回転をリセット

                    // テキスト描画
                    g2d.setFont(new Font("Meiryo", Font.BOLD, 24));
                    g2d.setColor(Color.BLACK);
                    g2d.drawString("Graphics2Dの機能", 50, 300);

                    // 複合図形
                    GeneralPath path = new GeneralPath();
                    path.moveTo(50, 350);
                    path.lineTo(150, 350);
                    path.curveTo(200, 350, 200, 400, 150, 400);
                    path.lineTo(50, 400);
                    path.closePath();

                    g2d.setPaint(new Color(255, 215, 0));
                    g2d.fill(path);
                }
            };

            frame.add(panel);
            frame.setVisible(true);
        });
    }
}

画像の表示と操作

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class ImageDrawingExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("画像描画例");
            frame.setSize(800, 600);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = new JPanel() {
                private BufferedImage image;

                {
                    try {
                        // 画像の読み込み(実際のパスに置き換えてください)
                        image = ImageIO.read(new File("sample.jpg"));
                    } catch (Exception e) {
                        e.printStackTrace();
                        // エラー時はダミー画像を作成
                        image = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
                        Graphics2D g2d = image.createGraphics();
                        g2d.setColor(Color.WHITE);
                        g2d.fillRect(0, 0, 400, 300);
                        g2d.setColor(Color.RED);
                        g2d.drawString("画像が読み込めません", 50, 150);
                        g2d.dispose();
                    }
                }

                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    Graphics2D g2d = (Graphics2D)g;

                    // 背景
                    g2d.setColor(Color.LIGHT_GRAY);
                    g2d.fillRect(0, 0, getWidth(), getHeight());

                    if (image != null) {
                        // 元のサイズで描画
                        g2d.drawImage(image, 50, 50, this);

                        // スケーリングして描画
                        int scaledWidth = image.getWidth() / 2;
                        int scaledHeight = image.getHeight() / 2;
                        g2d.drawImage(image, 300, 50, scaledWidth, scaledHeight, this);

                        // 画像処理(グレースケール)
                        BufferedImage grayImage = toGrayScale(image);
                        g2d.drawImage(grayImage, 50, 300, scaledWidth, scaledHeight, this);

                        // 回転して描画
                        g2d.rotate(Math.toRadians(30), 500, 400);
                        g2d.drawImage(image, 400, 300, scaledWidth, scaledHeight, this);
                        g2d.rotate(Math.toRadians(-30), 500, 400);
                    }
                }

                private BufferedImage toGrayScale(BufferedImage original) {
                    BufferedImage gray = new BufferedImage(
                        original.getWidth(), 
                        original.getHeight(), 
                        BufferedImage.TYPE_BYTE_GRAY);
                    Graphics g = gray.getGraphics();
                    g.drawImage(original, 0, 0, null);
                    g.dispose();
                    return gray;
                }
            };

            frame.add(panel);
            frame.setVisible(true);
        });
    }
}

アニメーションの実装

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

public class SimpleAnimation {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("簡単なアニメーション");
            frame.setSize(600, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            AnimationPanel panel = new AnimationPanel();
            frame.add(panel);

            // アニメーション用タイマー
            Timer timer = new Timer(50, panel);
            timer.start();

            frame.setVisible(true);
        });
    }
}

class AnimationPanel extends JPanel implements ActionListener {
    private int x = 0;
    private int y = 100;
    private int dx = 5;
    private int diameter = 50;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;

        // 背景
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, getWidth(), getHeight());

        // ボールの描画
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                           RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(70, 130, 180));
        g2d.fillOval(x, y, diameter, diameter);

        // 軌跡の表示
        g2d.setColor(new Color(70, 130, 180, 50));
        for (int i = 0; i < 10; i++) {
            int trailX = x - i * dx;
            if (trailX > 0) {
                g2d.fillOval(trailX, y, diameter, diameter);
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        x += dx;

        // 端に達したら反転
        if (x + diameter > getWidth() || x < 0) {
            dx = -dx;
        }

        repaint(); // 再描画を要求
    }
}

グラフィックス描画のベストプラクティス

  1. paintComponentのオーバーライド - paint()ではなくpaintComponent()をオーバーライド
  2. super.paintComponent()の呼び出し - 最初に親クラスのメソッドを呼び出して背景をクリア
  3. アンチエイリアシングの有効化 - 図形のジャギーを軽減
   g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                      RenderingHints.VALUE_ANTIALIAS_ON);
  1. リソースの解放 - Graphicsオブジェクトを使用後はdispose()で解放
  2. ダブルバッファリング - デフォルトで有効だが、カスタム描画でちらつく場合は確認
  3. パフォーマンス考慮 - 描画範囲を最小限に(clipRectの活用)
  4. スレッドセーフ - Swingの描画はイベントディスパッチスレッドで行う
// 部分的な再描画の例
public void updateCirclePosition(int newX, int newY) {
    // 古い位置と新しい位置の両方を再描画
    repaint(oldX, oldY, diameter, diameter);
    repaint(newX, newY, diameter, diameter);
    oldX = newX;
    oldY = newY;
}

これらの基本技術を組み合わせることで、Swingアプリケーションに豊かなビジュアル要素を追加できます。次に学ぶ「カスタムコンポーネントの作成」では、これらのグラフィックス技術を活用して独自のUIコンポーネントを作成する方法を解説します。