效果演示

完整程式碼
import java.awt.*;
import java.awt.event.*;
public class MouseFollowBall {
public static void main(String[] args) {
Frame frame = new Frame("Mouse Follow Ball");
frame.setSize(800, 600);
frame.setBackground(Color.BLACK);
BallPanel panel = new BallPanel();
frame.add(panel);
frame.addMouseMotionListener(panel); // 視窗層級監聽
panel.addMouseMotionListener(panel); // 面板層級監聽(雙重保險)
frame.setVisible(true);
}
}
class BallPanel extends Panel implements MouseMotionListener {
private int x = 150, y = 150; // 小球中心座標
@Override
public void paint(Graphics g) {
g.setColor(Color.WHITE);
g.fillOval(x - 10, y - 10, 20, 20); // 以中心點繪製 20x20 圓
}
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint(); // 觸發重繪
}
@Override
public void mouseDragged(MouseEvent e) {
// 拖曳時同樣更新座標
mouseMoved(e);
}
}
核心概念解析
| 介面/方法 | 說明 |
MouseMotionListener | 滑鼠移動/拖曳事件監聽介面 |
mouseMoved(MouseEvent) | 滑鼠無按鍵移動時觸發 |
mouseDragged(MouseEvent) | 滑鼠按住鍵移動時觸發 |
e.getX()/getY() | 取得事件發生座標(相對元件原點) |
repaint() | 非同步請求重繪,AWT 會合併多次呼叫 |
常見問題與優化
- 閃爍:AWT 預設無雙緩衝 → 改用
BufferedImage 離屏繪圖
- 座標偏移:若在
Frame 直接監聽,座標包含標題列高度 → 建議監聽 Panel
- 效能:高頻
repaint 可加入節流(如 16ms 一幀)
進階:拖曳移動小球
private boolean dragging = false;
@Override
public void mousePressed(MouseEvent e) {
if (Math.hypot(e.getX() - x, e.getY() - y) < 10) dragging = true;
}
@Override
public void mouseReleased(MouseEvent e) { dragging = false; }
@Override
public void mouseDragged(MouseEvent e) {
if (dragging) { x = e.getX(); y = e.getY(); repaint(); }
}