Swing/ScreenCapture のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ScreenCapture へ行く。
- 1 (2021-12-13 (月) 00:04:27)
- 2 (2022-08-23 (火) 13:09:20)
- 3 (2024-03-10 (日) 20:13:56)
- category: swing folder: ScreenCapture title: Robotを使用してスクリーンショットを取得する tags: [Robot, JFrame, BufferedImage, ConvolveOp] author: aterai pubdate: 2021-12-13T00:03:40+09:00 description: Robotを使用してスクリーンショット画像を取得して背景画像として描画することでJFrameを半透明に見せかけます。 image: https://drive.google.com/uc?id=1e9aL18WI4SjJp5iHgshLy4Kx0XGw0nMD
概要
Robot
を使用してスクリーンショット画像を取得して背景画像として描画することでJFrame
を半透明に見せかけます。
Screenshot
Advertisement
サンプルコード
private final transient Robot robot;
private final Rectangle screenRect;
private final Rectangle buf = new Rectangle();
private transient BufferedImage backgroundImage;
private final float[] data = {
.1f, .1f, .1f,
.1f, .2f, .1f,
.1f, .1f, .1f,
};
private Kernel kernel = new Kernel(3, 3, data);
private ConvolveOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
private Color bgc = new Color(255, 255, 255, 100);
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
Point pt = getLocationOnScreen();
buf.setBounds(screenRect);
SwingUtilities.computeIntersection(pt.x, pt.y, getWidth(), getHeight(), buf);
Image img = backgroundImage.getSubimage(buf.x, buf.y, buf.width, buf.height);
g2.drawImage(img, -Math.min(pt.x, 0), -Math.min(pt.y, 0), this);
g2.setPaint(bgc);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
}
public void updateBackground() {
backgroundImage = op.filter(robot.createScreenCapture(screenRect), null);
}
View in GitHub: Java, Kotlin解説
上記のサンプルではRobot#createScreenCapture(...)
メソッドを使用してデスクトップのスクリーンショットを取得してJPanel
の背景として描画することでJFrame
が半透明であるかのように表示しています。
Robot#createScreenCapture(...)
で取得した画像にConvolveOp
でぼかし効果を設定JPanel#getLocationOnScreen()
で取得した位置を左上にしてJPanel
と同じ幅と高さの矩形Rectangle
を作成JFrame
がスクリーンの外に配置されている場合などを除く必要があるため、SwingUtilities.computeIntersection(...)
でこの矩形とスクリーンサイズとの共通矩形を取得- スクリーン画像から
getSubimage(...)
で共通矩形の画像を取得 - 共通矩形の画像を
JPanel
に背景として描画- たとえば
JFrame
の左辺がスクリーンの左辺の外に存在する(JPanel#getLocationOnScreen()
で取得した位置がマイナスになる)場合は共通矩形の画像はJPanel
より幅が短くなるので注意が必要
- たとえば
JFrame
にComponentListener
を追加して移動やリサイズで背景画像を再描画JFrame
にWindowListener
を追加してアイコン化が解除されるとスクリーン画像を更新- たとえば別ウィンドウにフォーカス移動してその位置を変更したりマウスホイールなどでバックグラウンドのウィンドウを更新してもスクリーン画像は更新していないので
JFrame
に描画している背景画像とずれが発生する
参考リンク
- JFrameを半透明化 - Java Swing Tips
JFrame.setDefaultLookAndFeelDecorated(true); JFrame#setBackground(new Color(0x0, true));
などでJFrame
を半透明化する場合はSystemLookAndFeel
などで使用不可、またConvolveOp
などを適用してぼかし効果なども不可となる
- java - How to make the JFrame contentPane transparent but the JFrame visible? - Stack Overflow