Swing演習問題(30問)

2025-08-06

初級問題(9問)

  1. JDialogを使用してカスタムダイアログを作成し、”Hello Dialog”というタイトルを設定してください。
  2. MouseListenerを実装して、ボタンクリック時にマウスの座標を表示してください。
  3. Graphicsオブジェクトを使用して、JPanel上に赤色の四角形を描画してください。
  4. CardLayoutを使用して2つのパネルを切り替える基本的な設定を記述してください。
  5. マウスがコンポーネント上に入った時と出た時のイベントを検知し、コンソールにメッセージを出力してください。
  6. JPanel上に緑色の円を描画するコードを書いてください。
  7. カスタムダイアログにOKボタンを追加し、クリックでダイアログを閉じるようにしてください。
  8. マウスのドラッグ開始位置と終了位置を記録するコードを書いてください。
  9. CardLayoutでパネルを切り替えるボタンを作成してください。

中級問題(15問)

  1. モーダルダイアログを作成し、親フレームの操作をブロックするようにしてください。
  2. マウスのドラッグ操作で線を描画する簡単なお絵かきアプリを作成してください。
  3. Graphicsを使用して、JPanel上にグラデーションの背景を描画してください。
  4. CardLayoutを使用して3つ以上のパネルを管理し、前へ/次へボタンで切り替えてください。
  5. マウスホイールの回転を検知し、拡大縮小する処理を実装してください。
  6. カスタムダイアログに複数の入力フィールドを配置し、値を取得するコードを書いてください。
  7. マウスの右クリックでコンテキストメニューを表示する処理を実装してください。
  8. Graphics2Dを使用して、太い線と点線を描画するコードを書いてください。
  9. CardLayoutの各パネルに固有のタイトルを表示する仕組みを作成してください。
  10. マウスのダブルクリックを検知し、イベントを処理するコードを書いてください。
  11. ダイアログの結果に基づいてメイン画面の表示を変更するコードを書いてください。
  12. マウスのドラッグでコンポーネントを移動させるコードを書いてください。
  13. アンチエイリアスを有効にしたGraphics2Dで滑らかな図形を描画してください。
  14. CardLayoutを使用したウィザード形式(複数ステップ)のインターフェースを作成してください。
  15. マウスのクリック位置に図形(円など)を描画するコードを書いてください。

上級問題(6問)

  1. ドラッグ&ドロップで図形を配置・移動できるグラフィックエディタを作成してください。
  2. 複雑なカスタムダイアログ(タブ付き、検索機能付きリストなど)を作成してください。
  3. マウスジェスチャー認識システム(特定の動きでコマンド実行)を実装してください。
  4. カスタムレンダリングによる高度なグラフィックス(影付き図形、テクスチャなど)を実装してください。
  5. CardLayoutと履歴管理(戻る/進む機能)を組み合わせたナビゲーションシステムを作成してください。
  6. マウスイベントとグラフィックスを組み合わせたインタラクティブな図形編集ツールを作成してください。

Swing演習問題 解答例

初級問題解答

  1. カスタムダイアログ「Hello Dialog」
JDialog dialog = new JDialog(frame, "Hello Dialog", true);
dialog.setSize(300, 200);
dialog.setVisible(true);
  1. MouseListenerボタンクリック時にマウスの座標を表示
button.addMouseListener(new MouseAdapter() {
    public void mouseClicked(MouseEvent e) {
        System.out.println("Clicked at: " + e.getX() + "," + e.getY());
    }
});
  1. GraphicsでJPanel上に赤色の四角形を描画
class MyPanel extends JPanel {
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillRect(50, 50, 100, 80);
    }
}
  1. CardLayout2つのパネルを切り替える
CardLayout cardLayout = new CardLayout();
JPanel cardPanel = new JPanel(cardLayout);
cardPanel.add(new JPanel(), "Panel1");
cardPanel.add(new JPanel(), "Panel2");
  1. コンソールにメッセージを出力
component.addMouseListener(new MouseAdapter() {
    public void mouseEntered(MouseEvent e) {
        System.out.println("Mouse entered");
    }
    public void mouseExited(MouseEvent e) {
        System.out.println("Mouse exited");
    }
});
  1. JPanel上に緑色の円を描画
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.GREEN);
    g.fillOval(50, 50, 100, 100);
}
  1. カスタムダイアログにOKボタン
JButton okButton = new JButton("OK");
okButton.addActionListener(e -> dialog.dispose());
dialog.add(okButton);
  1. マウスのドラッグ開始位置と終了位置を記録
Point startPoint;
component.addMouseListener(new MouseAdapter() {
    public void mousePressed(MouseEvent e) {
        startPoint = e.getPoint();
    }
    public void mouseReleased(MouseEvent e) {
        Point endPoint = e.getPoint();
        System.out.println("Dragged from " + startPoint + " to " + endPoint);
    }
});
  1. CardLayoutでパネルを切り替える
JButton nextButton = new JButton("Next");
nextButton.addActionListener(e -> cardLayout.next(cardPanel));

中級問題解答

  1. モーダルダイアログで親フレームの操作をブロック
JDialog dialog = new JDialog(frame, "Modal Dialog", true);
// ダイアログ設定...
  1. 簡単なお絵かきアプリ
class DrawingPanel extends JPanel {
    private List points = new ArrayList<>();
    
    public DrawingPanel() {
        addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent e) {
                points.add(e.getPoint());
                repaint();
            }
        });
    }
    
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        for (int i = 1; i < points.size(); i++) {
            g2.drawLine(points.get(i-1).x, points.get(i-1).y, 
                        points.get(i).x, points.get(i).y);
        }
    }
}
  1. GraphicsでJPanel上にグラデーションの背景を描画
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    GradientPaint gp = new GradientPaint(0, 0, Color.BLUE, 
                                      getWidth(), getHeight(), Color.CYAN);
    g2d.setPaint(gp);
    g2d.fillRect(0, 0, getWidth(), getHeight());
}
  1. CardLayoutを使用して3つ以上のパネルを管理
JButton prevButton = new JButton("Previous");
prevButton.addActionListener(e -> cardLayout.previous(cardPanel));

JButton nextButton = new JButton("Next");
nextButton.addActionListener(e -> cardLayout.next(cardPanel));
  1. マウスホイールの回転を検知で拡大縮小する処理
addMouseWheelListener(e -> {
    int rotation = e.getWheelRotation();
    // 拡大縮小処理...
});
  1. カスタムダイアログから値を取得
JTextField field1 = new JTextField(20);
JTextField field2 = new JTextField(20);
JButton okButton = new JButton("OK");

okButton.addActionListener(e -> {
    String value1 = field1.getText();
    String value2 = field2.getText();
    // 値を使用...
    dialog.dispose();
});
  1. マウスの右クリックでコンテキストメニューを表示
JPopupMenu popupMenu = new JPopupMenu();
// メニュー項目追加...
component.setComponentPopupMenu(popupMenu);
  1. Graphics2D太い線と点線を描画
Graphics2D g2d = (Graphics2D)g;
g2d.setStroke(new BasicStroke(3)); // 太い線
g2d.drawLine(10, 10, 100, 10);

float[] dash = {5f, 3f};
g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, 
                            BasicStroke.JOIN_MITER, 1f, dash, 0f)); // 点線
g2d.drawLine(10, 20, 100, 20);
  1. CardLayoutの各パネルに固有のタイトルを表示
JLabel titleLabel = new JLabel("", JLabel.CENTER);

// カード切り替え時にタイトル更新
cardLayout.addLayoutComponent(cardPanel, "Title");
  1. マウスのダブルクリックを検知しイベント
addMouseListener(new MouseAdapter() {
    public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
            System.out.println("Double clicked");
        }
    }
});
  1. ダイアログの結果に基づいてメイン画面の表示
if (dialog.showDialog() == DialogResult.OK) {
    // ダイアログの結果に基づいて表示更新
}
  1. マウスのドラッグでコンポーネントを移動
addMouseMotionListener(new MouseMotionAdapter() {
    public void mouseDragged(MouseEvent e) {
        setLocation(e.getXOnScreen() - getWidth()/2, 
                   e.getYOnScreen() - getHeight()/2);
    }
});
  1. アンチエイリアスを有効にしたGraphics2Dで滑らかな図形
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawOval(50, 50, 100, 100);
  1. CardLayoutを使用したウィザード形式(複数ステップ)のインターフェース
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class WizardExample {
    private JFrame frame;
    private JPanel cardPanel;
    private CardLayout cardLayout;
    private JButton prevButton, nextButton;
    private int currentStep = 0;
    private final int TOTAL_STEPS = 3;

    public WizardExample() {
        frame = new JFrame("ウィザード形式アプリケーション");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);

        // CardLayoutの設定
        cardLayout = new CardLayout();
        cardPanel = new JPanel(cardLayout);

        // 各ステップのパネルを作成
        for (int i = 0; i < TOTAL_STEPS; i++) {
            JPanel stepPanel = new JPanel(new BorderLayout());
            stepPanel.add(new JLabel("ステップ " + (i + 1) + "/" + TOTAL_STEPS, JLabel.CENTER), BorderLayout.CENTER);
            
            // ステップごとに異なるコンポーネントを追加
            switch (i) {
                case 0:
                    stepPanel.add(new JLabel("基本情報を入力してください", JLabel.CENTER), BorderLayout.NORTH);
                    break;
                case 1:
                    stepPanel.add(new JLabel("詳細情報を入力してください", JLabel.CENTER), BorderLayout.NORTH);
                    break;
                case 2:
                    stepPanel.add(new JLabel("確認してください", JLabel.CENTER), BorderLayout.NORTH);
                    break;
            }
            
            cardPanel.add(stepPanel, "step" + i);
        }

        // ボタンパネル
        JPanel buttonPanel = new JPanel();
        prevButton = new JButton("前へ");
        nextButton = new JButton("次へ");
        JButton finishButton = new JButton("完了");

        prevButton.setEnabled(false);
        finishButton.setVisible(false);

        // ボタンアクション
        prevButton.addActionListener(e -> {
            if (currentStep > 0) {
                currentStep--;
                cardLayout.previous(cardPanel);
                updateButtons();
            }
        });

        nextButton.addActionListener(e -> {
            if (currentStep < TOTAL_STEPS - 1) {
                currentStep++;
                cardLayout.next(cardPanel);
                updateButtons();
            }
        });

        finishButton.addActionListener(e -> {
            JOptionPane.showMessageDialog(frame, "処理が完了しました!");
            frame.dispose();
        });

        buttonPanel.add(prevButton);
        buttonPanel.add(nextButton);
        buttonPanel.add(finishButton);

        // フレームに追加
        frame.add(cardPanel, BorderLayout.CENTER);
        frame.add(buttonPanel, BorderLayout.SOUTH);

        frame.setVisible(true);
    }

    private void updateButtons() {
        prevButton.setEnabled(currentStep > 0);
        nextButton.setEnabled(currentStep < TOTAL_STEPS - 1);
        
        if (currentStep == TOTAL_STEPS - 1) {
            nextButton.setVisible(false);
            ((JButton)((JPanel)nextButton.getParent()).getComponent(2)).setVisible(true);
        } else {
            nextButton.setVisible(true);
            ((JButton)((JPanel)nextButton.getParent()).getComponent(2)).setVisible(false);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(WizardExample::new);
    }
}
  1. マウスのクリック位置に図形(円など)を描画
List shapes = new ArrayList<>();
addMouseListener(new MouseAdapter() {
    public void mouseClicked(MouseEvent e) {
        shapes.add(new Ellipse2D.Double(e.getX()-10, e.getY()-10, 20, 20));
        repaint();
    }
});

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    for (Shape shape : shapes) {
        g2d.draw(shape);
    }
}

上級問題解答

  1. ドラッグ&ドロップで図形を配置・移動できるグラフィックエディタ
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;

public class ShapeEditor {
    private JFrame frame;
    private DrawingPanel drawingPanel;
    private ArrayList shapes = new ArrayList<>();
    private Shape selectedShape = null;
    private Point dragOffset;

    public ShapeEditor() {
        frame = new JFrame("図形エディタ");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 400);

        drawingPanel = new DrawingPanel();
        drawingPanel.setBackground(Color.WHITE);

        // 図形追加ボタン
        JButton addRectButton = new JButton("四角形追加");
        addRectButton.addActionListener(e -> {
            shapes.add(new Rectangle2D.Double(50, 50, 100, 80));
            drawingPanel.repaint();
        });

        JButton addCircleButton = new JButton("円追加");
        addCircleButton.addActionListener(e -> {
            shapes.add(new Ellipse2D.Double(50, 50, 100, 100));
            drawingPanel.repaint();
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(addRectButton);
        buttonPanel.add(addCircleButton);

        frame.add(drawingPanel, BorderLayout.CENTER);
        frame.add(buttonPanel, BorderLayout.SOUTH);
        frame.setVisible(true);
    }

    class DrawingPanel extends JPanel {
        public DrawingPanel() {
            addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                    // 図形選択
                    selectedShape = null;
                    for (Shape shape : shapes) {
                        if (shape.contains(e.getPoint())) {
                            selectedShape = shape;
                            dragOffset = new Point(
                                e.getX() - (int)((RectangularShape)shape).getX(),
                                e.getY() - (int)((RectangularShape)shape).getY()
                            );
                            break;
                        }
                    }
                    repaint();
                }

                public void mouseReleased(MouseEvent e) {
                    // 右クリックで図形削除
                    if (SwingUtilities.isRightMouseButton(e) && selectedShape != null) {
                        shapes.remove(selectedShape);
                        selectedShape = null;
                        repaint();
                    }
                }
            });

            addMouseMotionListener(new MouseMotionAdapter() {
                public void mouseDragged(MouseEvent e) {
                    if (selectedShape != null) {
                        // 図形移動
                        RectangularShape rectShape = (RectangularShape)selectedShape;
                        rectShape.setFrame(
                            e.getX() - dragOffset.x,
                            e.getY() - dragOffset.y,
                            rectShape.getWidth(),
                            rectShape.getHeight()
                        );
                        repaint();
                    }
                }
            });
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                               RenderingHints.VALUE_ANTIALIAS_ON);

            // すべての図形を描画
            for (Shape shape : shapes) {
                if (shape == selectedShape) {
                    g2d.setColor(Color.BLUE);
                    g2d.setStroke(new BasicStroke(2));
                } else {
                    g2d.setColor(Color.RED);
                    g2d.setStroke(new BasicStroke(1));
                }
                g2d.draw(shape);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ShapeEditor::new);
    }
}
  1. 複雑なカスタムダイアログ(タブ付き、検索機能付きリストなど)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.*;

public class ComplexDialogExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("メインウィンドウ");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        
        JButton showDialogButton = new JButton("ダイアログを表示");
        showDialogButton.addActionListener(e -> showCustomDialog(frame));
        
        frame.add(showDialogButton);
        frame.setVisible(true);
    }
    
    private static void showCustomDialog(JFrame parent) {
        // カスタムダイアログの作成
        JDialog dialog = new JDialog(parent, "高度な検索", true);
        dialog.setSize(500, 400);
        dialog.setLayout(new BorderLayout());
        
        // タブ付きペイン
        JTabbedPane tabbedPane = new JTabbedPane();
        
        // 1つ目のタブ - 検索条件
        JPanel searchPanel = new JPanel(new BorderLayout());
        
        // 検索フィールド
        JPanel searchFieldPanel = new JPanel();
        JTextField searchField = new JTextField(20);
        JButton searchButton = new JButton("検索");
        searchFieldPanel.add(new JLabel("検索語:"));
        searchFieldPanel.add(searchField);
        searchFieldPanel.add(searchButton);
        
        // フィルターオプション
        JPanel filterPanel = new JPanel(new GridLayout(0, 2, 5, 5));
        filterPanel.setBorder(BorderFactory.createTitledBorder("フィルターオプション"));
        
        JCheckBox caseSensitiveCheck = new JCheckBox("大文字小文字を区別");
        JCheckBox wholeWordCheck = new JCheckBox("単語単位で検索");
        JComboBox fileTypeCombo = new JComboBox<>(new String[]{"すべてのファイル", "テキストファイル", "画像ファイル", "PDF"});
        
        filterPanel.add(caseSensitiveCheck);
        filterPanel.add(wholeWordCheck);
        filterPanel.add(new JLabel("ファイルタイプ:"));
        filterPanel.add(fileTypeCombo);
        
        searchPanel.add(searchFieldPanel, BorderLayout.NORTH);
        searchPanel.add(filterPanel, BorderLayout.CENTER);
        
        // 2つ目のタブ - 検索結果
        JPanel resultsPanel = new JPanel(new BorderLayout());
        DefaultListModel resultsModel = new DefaultListModel<>();
        JList resultsList = new JList<>(resultsModel);
        JScrollPane scrollPane = new JScrollPane(resultsList);
        
        // ダミーデータを追加
        for (int i = 1; i <= 20; i++) {
            resultsModel.addElement("検索結果 " + i);
        }
        
        resultsPanel.add(scrollPane, BorderLayout.CENTER);
        
        // タブを追加
        tabbedPane.addTab("検索条件", searchPanel);
        tabbedPane.addTab("検索結果", resultsPanel);
        
        // 下部ボタンパネル
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        JButton okButton = new JButton("OK");
        JButton cancelButton = new JButton("キャンセル");
        JButton applyButton = new JButton("適用");
        
        buttonPanel.add(applyButton);
        buttonPanel.add(okButton);
        buttonPanel.add(cancelButton);
        
        // ダイアログにコンポーネントを追加
        dialog.add(tabbedPane, BorderLayout.CENTER);
        dialog.add(buttonPanel, BorderLayout.SOUTH);
        
        // ボタンアクション
        okButton.addActionListener(e -> {
            System.out.println("OKがクリックされました");
            dialog.dispose();
        });
        
        cancelButton.addActionListener(e -> dialog.dispose());
        
        // 検索ボタンのアクション
        searchButton.addActionListener(e -> {
            String searchText = searchField.getText();
            if (!searchText.isEmpty()) {
                tabbedPane.setSelectedIndex(1); // 結果タブに切り替え
                // ここで実際の検索処理を行う
            }
        });
        
        dialog.setLocationRelativeTo(parent);
        dialog.setVisible(true);
    }
}
  1. マウスジェスチャー認識システム(特定の動きでコマンド実行)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;

public class MouseGestureRecognizer {
    private JFrame frame;
    private DrawingPanel drawingPanel;
    private List mousePath = new ArrayList<>();
    private Timer gestureTimer;
    
    // ジェスチャーコマンド
    private enum GestureCommand { OPEN, SAVE, DELETE, COPY, PASTE, UNKNOWN }
    
    public MouseGestureRecognizer() {
        frame = new JFrame("マウスジェスチャー認識");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 400);
        
        drawingPanel = new DrawingPanel();
        frame.add(drawingPanel, BorderLayout.CENTER);
        
        JLabel statusLabel = new JLabel(" 右ボタンを押しながらマウスを動かしてジェスチャーを描いてください ");
        frame.add(statusLabel, BorderLayout.SOUTH);
        
        // ジェスチャー認識用タイマー
        gestureTimer = new Timer(1000, e -> {
            if (!mousePath.isEmpty()) {
                GestureCommand command = recognizeGesture(mousePath);
                statusLabel.setText("認識されたコマンド: " + command);
                mousePath.clear();
                drawingPanel.repaint();
            }
        });
        gestureTimer.setRepeats(false);
        
        frame.setVisible(true);
    }
    
    class DrawingPanel extends JPanel {
        public DrawingPanel() {
            setBackground(Color.WHITE);
            
            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    if (SwingUtilities.isRightMouseButton(e)) {
                        mousePath.clear();
                        mousePath.add(e.getPoint());
                    }
                }
                
                @Override
                public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isRightMouseButton(e) && mousePath.size() > 1) {
                        gestureTimer.restart();
                    }
                }
            });
            
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    if (SwingUtilities.isRightMouseButton(e)) {
                        mousePath.add(e.getPoint());
                        repaint();
                    }
                }
            });
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                               RenderingHints.VALUE_ANTIALIAS_ON);
            
            // マウスパスを描画
            if (mousePath.size() > 1) {
                g2d.setColor(Color.BLUE);
                g2d.setStroke(new BasicStroke(2));
                
                for (int i = 1; i < mousePath.size(); i++) {
                    Point p1 = mousePath.get(i-1);
                    Point p2 = mousePath.get(i);
                    g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
                }
            }
        }
    }
    
    private GestureCommand recognizeGesture(List path) {
        if (path.size() < 3) return GestureCommand.UNKNOWN;
        
        // 単純な方向ベースのジェスチャー認識
        Point first = path.get(0);
        Point last = path.get(path.size()-1);
        
        // 水平方向の動き
        if (Math.abs(last.y - first.y) < 50) {
            if (last.x > first.x + 100) return GestureCommand.OPEN;
            if (last.x < first.x - 100) return GestureCommand.SAVE;
        }
        
        // 垂直方向の動き
        if (Math.abs(last.x - first.x) < 50) {
            if (last.y > first.y + 100) return GestureCommand.DELETE;
            if (last.y < first.y - 100) return GestureCommand.COPY;
        }
        
        // 円形の動き
        double radius = calculateAverageRadius(path);
        if (radius > 30 && radius < 150) {
            return GestureCommand.PASTE;
        }
        
        return GestureCommand.UNKNOWN;
    }
    
    private double calculateAverageRadius(List path) {
        if (path.size() < 3) return 0;
        
        // 中心点を計算
        int sumX = 0, sumY = 0;
        for (Point p : path) {
            sumX += p.x;
            sumY += p.y;
        }
        Point center = new Point(sumX / path.size(), sumY / path.size());
        
        // 平均半径を計算
        double totalRadius = 0;
        for (Point p : path) {
            totalRadius += center.distance(p);
        }
        
        return totalRadius / path.size();
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(MouseGestureRecognizer::new);
    }
}
  1. カスタムレンダリングによる高度なグラフィックス(影付き図形、テクスチャなど)
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.awt.TexturePaint;

public class AdvancedGraphicsExample extends JFrame {
    private DrawingPanel drawingPanel;
    
    public AdvancedGraphicsExample() {
        setTitle("高度なグラフィックス描画");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        drawingPanel = new DrawingPanel();
        add(drawingPanel, BorderLayout.CENTER);
        
        setVisible(true);
    }
    
    class DrawingPanel extends JPanel {
        private BufferedImage texture;
        
        public DrawingPanel() {
            // テクスチャ画像を作成
            texture = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = texture.createGraphics();
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 20, 20);
            g2d.setColor(Color.BLUE);
            g2d.drawLine(0, 0, 20, 20);
            g2d.drawLine(20, 0, 0, 20);
            g2d.dispose();
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                               RenderingHints.VALUE_ANTIALIAS_ON);
            
            // 背景のグラデーション
            GradientPaint gradient = new GradientPaint(0, 0, new Color(240, 240, 240),
                                           getWidth(), getHeight(), Color.WHITE);
            g2d.setPaint(gradient);
            g2d.fillRect(0, 0, getWidth(), getHeight());
            
            // 影付きの四角形
            drawShapeWithShadow(g2d, new Rectangle2D.Double(50, 50, 200, 150), 
                              new Color(70, 130, 180), 5);
            
            // テクスチャ付きの円
            TexturePaint texturePaint = new TexturePaint(texture, 
                new Rectangle2D.Double(0, 0, texture.getWidth(), texture.getHeight()));
            g2d.setPaint(texturePaint);
            Ellipse2D circle = new Ellipse2D.Double(300, 100, 200, 200);
            g2d.fill(circle);
            
            // 透明な図形
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));
            g2d.setColor(new Color(220, 20, 60));
            g2d.fill(new RoundRectangle2D.Double(400, 350, 250, 150, 30, 30));
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
            
            // 複雑なパス(星形)
            GeneralPath star = new GeneralPath();
            star.moveTo(150, 350);
            star.lineTo(180, 450);
            star.lineTo(100, 390);
            star.lineTo(200, 390);
            star.lineTo(120, 450);
            star.closePath();
            
            // グラデーションで塗りつぶし
            GradientPaint starGradient = new GradientPaint(150, 350, Color.YELLOW, 
                                                       200, 450, Color.ORANGE);
            g2d.setPaint(starGradient);
            g2d.fill(star);
            
            // 太い境界線
            g2d.setStroke(new BasicStroke(5));
            g2d.setColor(Color.BLACK);
            g2d.draw(star);
            
            // テキストの描画(影付き)
            Font font = new Font("Serif", Font.BOLD | Font.ITALIC, 48);
            g2d.setFont(font);
            
            String text = "Swing Graphics";
            
            // 影
            g2d.setColor(new Color(0, 0, 0, 100));
            g2d.drawString(text, 253, 303);
            
            // メインテキスト
            g2d.setColor(new Color(30, 144, 255));
            g2d.drawString(text, 250, 300);
        }
        
        private void drawShapeWithShadow(Graphics2D g2d, Shape shape, Color color, int shadowSize) {
            // 影を描画
            g2d.setColor(new Color(0, 0, 0, 50));
            for (int i = 1; i <= shadowSize; i++) {
                AffineTransform shadowTransform = AffineTransform.getTranslateInstance(i, i);
                g2d.fill(shadowTransform.createTransformedShape(shape));
            }
            
            // 図形を描画
            GradientPaint shapeGradient = new GradientPaint(
                (float)shape.getBounds().getMinX(), 
                (float)shape.getBounds().getMinY(), 
                color.brighter(),
                (float)shape.getBounds().getMaxX(), 
                (float)shape.getBounds().getMaxY(), 
                color.darker());
            
            g2d.setPaint(shapeGradient);
            g2d.fill(shape);
            
            g2d.setColor(color.darker().darker());
            g2d.setStroke(new BasicStroke(2));
            g2d.draw(shape);
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(AdvancedGraphicsExample::new);
    }
}
  1. CardLayoutと履歴管理(戻る/進む機能)を組み合わせたナビゲーションシステム
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Stack;

public class NavigationSystem {
    private JFrame frame;
    private JPanel cardPanel;
    private CardLayout cardLayout;
    private Stack history = new Stack<>();
    private JButton backButton, forwardButton;
    private String currentCard;

    public NavigationSystem() {
        frame = new JFrame("履歴管理システム");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 400);

        // CardLayoutの設定
        cardLayout = new CardLayout();
        cardPanel = new JPanel(cardLayout);

        // カード(画面)を追加
        String[] cards = {"ホーム", "製品", "サービス", "お問い合わせ", "設定"};
        for (String card : cards) {
            JPanel panel = new JPanel(new BorderLayout());
            panel.add(new JLabel(card + "画面", JLabel.CENTER), BorderLayout.CENTER);
            
            // 各カードに移動用ボタンを追加
            JPanel navPanel = new JPanel();
            for (String navCard : cards) {
                if (!navCard.equals(card)) {
                    JButton navButton = new JButton(navCard + "へ");
                    navButton.addActionListener(e -> navigateTo(navCard));
                    navPanel.add(navButton);
                }
            }
            panel.add(navPanel, BorderLayout.SOUTH);
            
            cardPanel.add(panel, card);
        }

        // ナビゲーションボタン
        backButton = new JButton("← 戻る");
        forwardButton = new JButton("進む →");
        JButton homeButton = new JButton("ホーム");
        
        backButton.setEnabled(false);
        forwardButton.setEnabled(false);

        // ボタンアクション
        backButton.addActionListener(e -> goBack());
        forwardButton.addActionListener(e -> goForward());
        homeButton.addActionListener(e -> navigateTo("ホーム"));

        JPanel controlPanel = new JPanel();
        controlPanel.add(backButton);
        controlPanel.add(forwardButton);
        controlPanel.add(homeButton);

        // 初期画面表示
        navigateTo("ホーム");

        frame.add(cardPanel, BorderLayout.CENTER);
        frame.add(controlPanel, BorderLayout.SOUTH);
        frame.setVisible(true);
    }

    private void navigateTo(String cardName) {
        if (currentCard != null && !currentCard.equals(cardName)) {
            history.push(currentCard);
            backButton.setEnabled(true);
            forwardButton.setEnabled(false);
        }
        currentCard = cardName;
        cardLayout.show(cardPanel, cardName);
    }

    private void goBack() {
        if (!history.isEmpty()) {
            String previousCard = history.pop();
            forwardButton.setEnabled(true);
            if (history.isEmpty()) {
                backButton.setEnabled(false);
            }
            cardLayout.show(cardPanel, previousCard);
            currentCard = previousCard;
        }
    }

    private void goForward() {
        // 簡易実装(実際には進む履歴も管理する必要あり)
        forwardButton.setEnabled(false);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(NavigationSystem::new);
    }
}
  1. マウスイベントとグラフィックスを組み合わせたインタラクティブな図形編集ツール
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;

public class InteractiveShapeEditor extends JFrame {
    private DrawingPanel drawingPanel;
    private List shapes = new ArrayList<>();
    private Shape selectedShape = null;
    private Point dragStartPoint;
    private int resizeHandle = -1; // リサイズハンドルのインデックス (-1 = 選択なし)
    private final int HANDLE_SIZE = 8;
    
    // 図形の種類
    private enum ShapeType { RECTANGLE, ELLIPSE, LINE }
    private ShapeType currentShapeType = ShapeType.RECTANGLE;
    
    public InteractiveShapeEditor() {
        setTitle("インタラクティブ図形編集ツール");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        drawingPanel = new DrawingPanel();
        add(drawingPanel, BorderLayout.CENTER);
        
        // ツールバーの作成
        JToolBar toolBar = new JToolBar();
        
        // 図形選択ボタン
        ButtonGroup shapeGroup = new ButtonGroup();
        JToggleButton rectButton = new JToggleButton("四角形", true);
        JToggleButton ellipseButton = new JToggleButton("円");
        JToggleButton lineButton = new JToggleButton("直線");
        
        rectButton.addActionListener(e -> currentShapeType = ShapeType.RECTANGLE);
        ellipseButton.addActionListener(e -> currentShapeType = ShapeType.ELLIPSE);
        lineButton.addActionListener(e -> currentShapeType = ShapeType.LINE);
        
        shapeGroup.add(rectButton);
        shapeGroup.add(ellipseButton);
        shapeGroup.add(lineButton);
        
        toolBar.add(rectButton);
        toolBar.add(ellipseButton);
        toolBar.add(lineButton);
        
        // 色選択ボタン
        JButton colorButton = new JButton("色選択");
        colorButton.addActionListener(e -> {
            Color newColor = JColorChooser.showDialog(this, "色を選択", Color.RED);
            if (newColor != null && selectedShape != null) {
                drawingPanel.setShapeColor(selectedShape, newColor);
            }
        });
        toolBar.add(colorButton);
        
        // 削除ボタン
        JButton deleteButton = new JButton("削除");
        deleteButton.addActionListener(e -> {
            if (selectedShape != null) {
                shapes.remove(selectedShape);
                selectedShape = null;
                drawingPanel.repaint();
            }
        });
        toolBar.add(deleteButton);
        
        add(toolBar, BorderLayout.NORTH);
        
        setVisible(true);
    }
    
    class DrawingPanel extends JPanel {
        private HashMap shapeColors = new HashMap<>();
        private HashMap shapeStrokes = new HashMap<>();
        
        public DrawingPanel() {
            setBackground(Color.WHITE);
            
            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    dragStartPoint = e.getPoint();
                    selectedShape = null;
                    resizeHandle = -1;
                    
                    // 既存の図形を選択
                    for (Shape shape : shapes) {
                        if (shape.contains(e.getPoint())) {
                            selectedShape = shape;
                            break;
                        }
                    }
                    
                    // リサイズハンドルをチェック
                    if (selectedShape != null) {
                        resizeHandle = getResizeHandleAt(e.getPoint(), selectedShape);
                    }
                    
                    // 新しい図形を作成
                    if (selectedShape == null && !SwingUtilities.isRightMouseButton(e)) {
                        createNewShape(e.getPoint());
                    }
                    
                    repaint();
                }
                
                @Override
                public void mouseReleased(MouseEvent e) {
                    if (selectedShape != null && e.getPoint().equals(dragStartPoint)) {
                        // クリックのみ(ドラッグなし)の場合は選択状態のみ変更
                    }
                    repaint();
                }
            });
            
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    if (selectedShape != null) {
                        if (resizeHandle >= 0) {
                            // リサイズ処理
                            resizeShape(e.getPoint());
                        } else {
                            // 移動処理
                            moveShape(e.getPoint());
                        }
                        repaint();
                    }
                }
            });
        }
        
        private void createNewShape(Point p) {
            Shape newShape = null;
            Color color = new Color(
                (int)(Math.random() * 256),
                (int)(Math.random() * 256),
                (int)(Math.random() * 256)
            );
            
            switch (currentShapeType) {
                case RECTANGLE:
                    newShape = new Rectangle2D.Double(p.x, p.y, 1, 1);
                    break;
                case ELLIPSE:
                    newShape = new Ellipse2D.Double(p.x, p.y, 1, 1);
                    break;
                case LINE:
                    newShape = new Line2D.Double(p.x, p.y, p.x, p.y);
                    break;
            }
            
            shapes.add(newShape);
            selectedShape = newShape;
            shapeColors.put(newShape, color);
            shapeStrokes.put(newShape, new BasicStroke(2));
        }
        
        private void moveShape(Point p) {
            double dx = p.x - dragStartPoint.x;
            double dy = p.y - dragStartPoint.y;
            dragStartPoint = p;
            
            if (selectedShape instanceof Rectangle2D) {
                Rectangle2D rect = (Rectangle2D)selectedShape;
                rect.setRect(
                    rect.getX() + dx,
                    rect.getY() + dy,
                    rect.getWidth(),
                    rect.getHeight()
                );
            } else if (selectedShape instanceof Ellipse2D) {
                Ellipse2D ellipse = (Ellipse2D)selectedShape;
                ellipse.setFrame(
                    ellipse.getX() + dx,
                    ellipse.getY() + dy,
                    ellipse.getWidth(),
                    ellipse.getHeight()
                );
            } else if (selectedShape instanceof Line2D) {
                Line2D line = (Line2D)selectedShape;
                line.setLine(
                    line.getX1() + dx,
                    line.getY1() + dy,
                    line.getX2() + dx,
                    line.getY2() + dy
                );
            }
        }
        
        private void resizeShape(Point p) {
            if (selectedShape instanceof Rectangle2D) {
                Rectangle2D rect = (Rectangle2D)selectedShape;
                double newWidth = p.x - rect.getX();
                double newHeight = p.y - rect.getY();
                
                if (newWidth > 10 && newHeight > 10) {
                    rect.setRect(
                        rect.getX(),
                        rect.getY(),
                        newWidth,
                        newHeight
                    );
                }
            } else if (selectedShape instanceof Ellipse2D) {
                Ellipse2D ellipse = (Ellipse2D)selectedShape;
                double newWidth = p.x - ellipse.getX();
                double newHeight = p.y - ellipse.getY();
                
                if (newWidth > 10 && newHeight > 10) {
                    ellipse.setFrame(
                        ellipse.getX(),
                        ellipse.getY(),
                        newWidth,
                        newHeight
                    );
                }
            } else if (selectedShape instanceof Line2D) {
                Line2D line = (Line2D)selectedShape;
                line.setLine(
                    line.getX1(),
                    line.getY1(),
                    p.x,
                    p.y
                );
            }
        }
        
        private int getResizeHandleAt(Point p, Shape shape) {
            if (shape instanceof Rectangle2D || shape instanceof Ellipse2D) {
                Rectangle2D bounds = shape.getBounds2D();
                Point2D[] handles = {
                    new Point2D.Double(bounds.getMaxX(), bounds.getMaxY()), // 右下
                    new Point2D.Double(bounds.getMinX(), bounds.getMaxY()), // 左下
                    new Point2D.Double(bounds.getMaxX(), bounds.getMinY()), // 右上
                    new Point2D.Double(bounds.getMinX(), bounds.getMinY())  // 左上
                };
                
                for (int i = 0; i < handles.length; i++) {
                    if (p.distance(handles[i]) < HANDLE_SIZE) {
                        return i;
                    }
                }
            }
            return -1;
        }
        
        public void setShapeColor(Shape shape, Color color) {
            shapeColors.put(shape, color);
            repaint();
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                               RenderingHints.VALUE_ANTIALIAS_ON);
            
            // すべての図形を描画
            for (Shape shape : shapes) {
                if (shape == selectedShape) {
                    g2d.setColor(shapeColors.get(shape).darker());
                    g2d.setStroke(new BasicStroke(3));
                } else {
                    g2d.setColor(shapeColors.get(shape));
                    g2d.setStroke(shapeStrokes.get(shape));
                }
                
                g2d.draw(shape);
                
                // 選択された図形のリサイズハンドルを描画
                if (shape == selectedShape && 
                    (shape instanceof Rectangle2D || shape instanceof Ellipse2D)) {
                    Rectangle2D bounds = shape.getBounds2D();
                    g2d.setColor(Color.BLUE);
                    g2d.fillRect(
                        (int)bounds.getMaxX() - HANDLE_SIZE/2,
                        (int)bounds.getMaxY() - HANDLE_SIZE/2,
                        HANDLE_SIZE, HANDLE_SIZE
                    );
                }
            }
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new InteractiveShapeEditor());
    }
}