マウスイベント処理(MouseListenerとMouseMotionListener)

2025-08-06

Swingアプリケーションでマウス操作を検知し、インタラクティブな機能を実装するには、マウスイベント処理の仕組みを理解する必要があります。SwingではMouseListenerMouseMotionListenerインターフェースを使用してマウス操作を処理します。

マウスイベントの種類

eventhandling

主要なマウスイベント

イベント発生条件
mouseClickedマウスクリック(押して離す)
mousePressedマウスボタンを押した時
mouseReleasedマウスボタンを離した時
mouseEnteredコンポーネント内にマウスが入った時
mouseExitedコンポーネントからマウスが出た時
mouseDraggedマウスボタンを押しながら移動
mouseMovedマウスボタンを押さずに移動

基本的なマウスイベント処理

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

public class BasicMouseEvents {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("基本的なマウスイベント");
            frame.setSize(500, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = new JPanel();
            JLabel statusLabel = new JLabel("マウスイベント待機中...", SwingConstants.CENTER);

            // MouseListenerの実装
            panel.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    statusLabel.setText(String.format(
                        "クリック位置: X=%d, Y=%d, クリック数=%d",
                        e.getX(), e.getY(), e.getClickCount()));
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    panel.setBackground(Color.LIGHT_GRAY);
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    panel.setBackground(null);
                }
            });

            // MouseMotionListenerの実装
            panel.addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    statusLabel.setText(String.format(
                        "マウス移動中: X=%d, Y=%d", e.getX(), e.getY()));
                }
            });

            frame.add(panel, BorderLayout.CENTER);
            frame.add(statusLabel, BorderLayout.SOUTH);
            frame.setVisible(true);
        });
    }
}

マウスドラッグ処理の実装

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

public class MouseDragExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("マウスドラッグ例");
            frame.setSize(600, 500);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            DrawPanel drawPanel = new DrawPanel();
            frame.add(drawPanel);
            frame.setVisible(true);
        });
    }
}

class DrawPanel extends JPanel {
    private Point startPoint;
    private Point endPoint;
    private final java.util.List shapes = new java.util.ArrayList<>();

    public DrawPanel() {
        setBackground(Color.WHITE);

        // マウスリスナーの追加
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                startPoint = e.getPoint();
                endPoint = startPoint;
                repaint();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                shapes.add(new Line2D.Double(startPoint, endPoint));
                startPoint = null;
                endPoint = null;
                repaint();
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                endPoint = 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);
        g2d.setColor(Color.BLUE);
        g2d.setStroke(new BasicStroke(3));

        // 保存された図形を描画
        for (Shape shape : shapes) {
            g2d.draw(shape);
        }

        // ドラッグ中の線を描画
        if (startPoint != null && endPoint != null) {
            g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
        }
    }
}

マウスホイールイベント処理

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

public class MouseWheelExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("マウスホイール例");
            frame.setSize(500, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = new JPanel(new BorderLayout());
            JLabel zoomLabel = new JLabel("ズーム: 100%", SwingConstants.CENTER);
            zoomLabel.setFont(new Font("Meiryo", Font.BOLD, 24));

            panel.add(zoomLabel, BorderLayout.CENTER);

            // マウスホイールリスナーの追加
            panel.addMouseWheelListener(e -> {
                int rotation = e.getWheelRotation();
                String currentText = zoomLabel.getText();
                int currentZoom = Integer.parseInt(currentText.replaceAll("[^0-9]", ""));

                int newZoom = currentZoom - (rotation * 10);
                if (newZoom < 10) newZoom = 10;
                if (newZoom > 300) newZoom = 300;

                zoomLabel.setText("ズーム: " + newZoom + "%");
            });

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

右クリック(コンテキストメニュー)の処理

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

public class RightClickMenuExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("右クリックメニュー例");
            frame.setSize(500, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JTextArea textArea = new JTextArea();
            frame.add(new JScrollPane(textArea));

            // ポップアップメニューの作成
            JPopupMenu popupMenu = new JPopupMenu();

            JMenuItem cutItem = new JMenuItem("切り取り");
            cutItem.addActionListener(e -> textArea.cut());

            JMenuItem copyItem = new JMenuItem("コピー");
            copyItem.addActionListener(e -> textArea.copy());

            JMenuItem pasteItem = new JMenuItem("貼り付け");
            pasteItem.addActionListener(e -> textArea.paste());

            popupMenu.add(cutItem);
            popupMenu.add(copyItem);
            popupMenu.add(pasteItem);

            // テキストエリアにマウスリスナーを追加
            textArea.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    maybeShowPopup(e);
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    maybeShowPopup(e);
                }

                private void maybeShowPopup(MouseEvent e) {
                    if (e.isPopupTrigger()) {
                        // メニュー項目の有効/無効を設定
                        cutItem.setEnabled(textArea.getSelectionEnd() > textArea.getSelectionStart());
                        copyItem.setEnabled(textArea.getSelectionEnd() > textArea.getSelectionStart());

                        popupMenu.show(e.getComponent(), e.getX(), e.getY());
                    }
                }
            });

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

ドラッグ&ドロップの基本実装

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;

public class DragAndDropExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("ドラッグ&ドロップ例");
            frame.setSize(600, 400);
            frame.setLayout(new GridLayout(2, 1));
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // ドラッグ元パネル
            JPanel dragSource = new JPanel();
            dragSource.setBackground(Color.LIGHT_GRAY);
            dragSource.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
            dragSource.add(new JLabel("ドラッグ元 (ここからテキストをドラッグ)"));

            // ドロップ先パネル
            JTextArea dropTarget = new JTextArea();
            dropTarget.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
            dropTarget.setText("ドロップ先 (ここにテキストをドロップ)");

            // ドラッグソースの設定
            dragSource.setTransferHandler(new TransferHandler("text"));
            dragSource.addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                    JComponent comp = (JComponent)e.getSource();
                    TransferHandler handler = comp.getTransferHandler();
                    handler.exportAsDrag(comp, e, TransferHandler.COPY);
                }
            });

            // ドロップターゲットの設定
            dropTarget.setTransferHandler(new TransferHandler() {
                @Override
                public boolean canImport(TransferSupport support) {
                    return support.isDataFlavorSupported(DataFlavor.stringFlavor);
                }

                @Override
                public boolean importData(TransferSupport support) {
                    try {
                        String data = (String)support.getTransferable()
                            .getTransferData(DataFlavor.stringFlavor);
                        JTextArea ta = (JTextArea)support.getComponent();
                        ta.setText(ta.getText() + "\n" + data);
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return false;
                }
            });

            frame.add(dragSource);
            frame.add(new JScrollPane(dropTarget));
            frame.setVisible(true);
        });
    }
}

マウスイベント処理のベストプラクティス

  1. MouseAdapterの使用 – 必要なメソッドだけをオーバーライド
  2. イベントスレッドの考慮 – 重い処理はSwingWorkerで別スレッドで実行
  3. マウスボタンの判別MouseEvent.getButton()でどのボタンが押されたか確認
   if (e.getButton() == MouseEvent.BUTTON3) {
       // 右クリック処理
   }
  1. 修飾キーの検出MouseEvent.getModifiersEx()でShift/Ctrl/Altキーの状態を取得
  2. ダブルクリックの処理MouseEvent.getClickCount()でクリック数を確認
  3. パフォーマンス考慮 – マウス移動イベントでは最小限の処理のみ行う
  4. ドラッグ操作の最適化 – ドラッグ中は軽量な描画を使用
// 修飾キーの検出例
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) {
    // Ctrlキーが押されている場合の処理
}

マウスイベントを適切に処理することで、直感的で操作性の高いGUIアプリケーションを作成できます。次に学ぶ「キーボードイベント処理」では、キーボード操作への対応方法を解説します。