java.awt.RobotRobot.createScreenCapture(Rectangle) 可擷取螢幕指定矩形區域,回傳 BufferedImage。此為截圖、遠端桌面、自動化測試基礎。
public class ScreenCapture {
private static final ScreenCapture INSTANCE = new ScreenCapture();
private final Robot robot;
private final JDialog dialog = new JDialog();
private final ImageLabel imageLabel = new ImageLabel();
private BufferedImage fullScreenImage, pickedImage;
private int x1, y1, x2, y2, recX, recY, recW, recH;
private boolean isFirstPoint = true;
private ScreenCapture() {
try { robot = new Robot(); }
catch (AWTException e) { throw new RuntimeException(e); }
// 設定全螢幕無邊框對話框供使用者框選區域
dialog.setUndecorated(true);
dialog.setAlwaysOnTop(true);
dialog.setModal(true);
dialog.setSize(Toolkit.getDefaultToolkit().getScreenSize());
dialog.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
JPanel cp = (JPanel) dialog.getContentPane();
cp.setLayout(new BorderLayout());
cp.add(imageLabel, BorderLayout.CENTER);
// 滑鼠事件:框選矩形
imageLabel.addMouseListener(new MouseAdapter() {
@Override public void mouseReleased(MouseEvent e) {
isFirstPoint = true;
pickedImage = fullScreenImage.getSubimage(recX, recY, recW, recH);
dialog.setVisible(false);
}
});
imageLabel.addMouseMotionListener(new MouseMotionAdapter() {
@Override public void mouseDragged(MouseEvent e) {
if (isFirstPoint) { x1 = e.getX(); y1 = e.getY(); isFirstPoint = false; }
else { x2 = e.getX(); y2 = e.getY(); updateRect(); }
}
@Override public void mouseMoved(MouseEvent e) { imageLabel.setCrosshair(e.getX(), e.getY()); }
});
}
private void updateRect() {
recX = Math.min(x1, x2); recY = Math.min(y1, y2);
recW = Math.abs(x2 - x1); recH = Math.abs(y2 - y1);
imageLabel.setRect(recX, recY, recW, recH);
}
public static ScreenCapture getInstance() { return INSTANCE; }
// 擷取全螢幕並開啟框選 UI
public void captureImage() {
fullScreenImage = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
imageLabel.setIcon(new ImageIcon(fullScreenImage));
dialog.setVisible(true);
}
public BufferedImage getPickedImage() { return pickedImage; }
public ImageIcon getPickedIcon() { return new ImageIcon(pickedImage); }
public void saveAsPNG(File file) throws IOException { ImageIO.write(pickedImage, "png", file); }
public void saveAsJPEG(File file) throws IOException { ImageIO.write(pickedImage, "jpeg", file); }
public void write(OutputStream out) throws IOException { ImageIO.write(pickedImage, "png", out); }
}
// 自訂 JLabel 繪製十字線與選取框
class ImageLabel extends JLabel {
private int rectX, rectY, rectW, rectH, crossX, crossY;
public void setRect(int x, int y, int w, int h) { rectX=x; rectY=y; rectW=w; rectH=h; repaint(); }
public void setCrosshair(int x, int y) { crossX=x; crossY=y; repaint(); }
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (rectW > 0 && rectH > 0) {
g.drawRect(rectX, rectY, rectW, rectH);
g.drawString(rectW + " x " + rectH, rectX + rectW/2 - 15, rectY + rectH/2);
}
g.drawLine(crossX, 0, crossX, getHeight());
g.drawLine(0, crossY, getWidth(), crossY);
}
}
JDialog 佔滿螢幕,捕捉滑鼠事件。paintComponent 繪製十字線與選取框,尺寸即時顯示。BufferedImage.getSubimage(x, y, w, h) 零拷貝共享資料,極快。ImageIO.write 支援 PNG、JPEG 等,可直接寫入檔案或串流(傳輸)。captureImage() → write(socket.getOutputStream())。ImageIO.read(inputStream) → 顯示於 JLabel。Robot.mouseMove/keyPress 重放。注意:生產環境需加入壓縮(如 JPEG 品質調整)、差異編碼、權限控管等。