Java AWT 提供 MouseInfo.getPointerInfo().getLocation() 即可獲取全螢幕滑鼠座標。本文構建一個置頂、無邊框、半透明、即時刷新的 Swing 小工具,展示 MouseInfo、TimerTask 定時輪詢、JDialog 視窗屬性設定的完整代碼,並討論跨螢幕、高 DPI、權限等實務考量。
// 靜態方法,無需實例化
PointerInfo pi = MouseInfo.getPointerInfo();
if (pi != null) {
Point pt = pi.getLocation(); // x, y 為螢幕絕對座標
System.out.println("X=" + pt.x + ", Y=" + pt.y);
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
public class MouseLocator extends JDialog {
private final JLabel lblX = new JLabel("X: 0");
private final JLabel lblY = new JLabel("Y: 0");
private final Timer timer = new Timer("MouseLocator", true); // daemon
public MouseLocator() {
// 1. 視窗屬性:無邊框、置頂、半透明、不進任務欄
setUndecorated(true);
setAlwaysOnTop(true);
setType(Type.UTILITY); // 不顯示在任務欄
setBackground(new Color(0, 0, 0, 0)); // 支援半透明
setLayout(new BorderLayout(5, 5));
// 2. 內容面板:半透明背景 + 文字
JPanel panel = new JPanel(new GridLayout(2, 2, 5, 5)) {
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(new Color(0, 0, 0, 180));
g2.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
g2.dispose();
}
};
panel.setOpaque(false);
panel.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 15));
Font font = new Font("微軟正黑體", Font.BOLD, 18);
lblX.setFont(font); lblX.setForeground(Color.WHITE);
lblY.setFont(font); lblY.setForeground(Color.WHITE);
panel.add(new JLabel("X:")); panel.add(lblX);
panel.add(new JLabel("Y:")); panel.add(lblY);
add(panel, BorderLayout.CENTER);
// 3. 拖拽移動 (無邊框需自行實現)
panel.addMouseListener(new MouseAdapter() {
Point dragStart;
public void mousePressed(MouseEvent e) { dragStart = e.getPoint(); }
public void mouseReleased(MouseEvent e) { dragStart = null; }
});
panel.addMouseMotionListener(new MouseMotionAdapter() {
Point dragStart;
public void mouseDragged(MouseEvent e) {
if (dragStart != null) {
Point loc = getLocation();
setLocation(loc.x + e.getX() - dragStart.x,
loc.y + e.getY() - dragStart.y);
}
}
});
// 4. 關閉鍵:ESC
getRootPane().registerKeyboardAction(e -> dispose(),
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
pack();
setLocation(100, 100);
setVisible(true);
// 5. 定時輪詢 (100ms = 10fps)
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
PointerInfo pi = MouseInfo.getPointerInfo();
if (pi != null) {
Point pt = pi.getLocation();
SwingUtilities.invokeLater(() -> {
lblX.setText("X: " + pt.x);
lblY.setText("Y: " + pt.y);
});
}
}
}, 0, 100);
}
public static void main(String[] args) {
// 啟用系統外觀 (可選)
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ignored) {}
SwingUtilities.invokeLater(MouseLocator::new);
}
}
| 需求 | 實現方式 |
|---|---|
| 置頂不被遮蓋 | setAlwaysOnTop(true) |
| 不佔用任務欄/Alt+Tab | setType(Type.UTILITY) (Java 7+) |
| 半透明圓角背景 | setUndecorated(true) + setBackground(new Color(0,0,0,0)) + 覆寫 paintComponent |
| 拖拽移動 | 滑鼠事件計算偏移 setLocation |
| ESC 關閉 | registerKeyboardAction + KeyStroke(VK_ESCAPE) |
| 定時器不阻塞退出 | new Timer(name, true) daemon 執行緒 |
| UI 更新線程安全 | SwingUtilities.invokeLater |
getLocation() 返回虛擬螢幕絕對座標 (主螢幕左上為 0,0),副螢幕在左/上方時座標為負數,正常。GraphicsDevice.getDisplayMode() 可查)。timer.cancel(),避免 daemon 執行緒殘留 (雖 daemon 隨 JVM 結束自動回收)。Robot.getPixelColor(x, y) 顯示滑鼠下像素 RGB/HEX。jpackage 生成原生安裝包 (exe/dmg/deb),含 JRE、圖標、檔案關聯。MouseInfo.getPointerInfo().getLocation() 是 Java 獲取全域滑鼠座標的標準 API。結合 JDialog 無邊框置頂視窗、Timer 定時輪詢、SwingUtilities.invokeLater 線程安全更新,即可構建專業級座標拾取小工具。注意高 DPI 縮放、Wayland/macOS 權限、多螢幕負座標三大實務坑點,並善用 jpackage 打包分發,即得開箱即用的開發輔助工具。