Swing/ScreenCapture の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/ScreenCapture へ行く。
- Swing/ScreenCapture の差分を削除
--- category: swing folder: ScreenCapture title: Robotを使用してスクリーンショットを取得する tags: [Robot, JFrame, BufferedImage, ConvolveOp] author: aterai pubdate: 2021-12-13T00:03:40+09:00 description: Robotを使用してスクリーンショット画像を取得して背景画像として描画することでJFrameを半透明に見せかけます。 description: Robotでスクリーンショット画像を取得し、背景画像として描画することでJFrameを半透明に見せかけます。 image: https://drive.google.com/uc?id=1e9aL18WI4SjJp5iHgshLy4Kx0XGw0nMD --- * 概要 [#summary] `Robot`を使用してスクリーンショット画像を取得して背景画像として描画することで`JFrame`を半透明に見せかけます。 `Robot`をでスクリーンショット画像を取得し、背景画像として描画することで`JFrame`を半透明に見せかけます。 #download(https://drive.google.com/uc?id=1e9aL18WI4SjJp5iHgshLy4Kx0XGw0nMD) * サンプルコード [#sourcecode] #code(link){{ 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); } }} * 解説 [#explanation] 上記のサンプルでは`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`に描画している背景画像とずれが発生する * 参考リンク [#reference] - [[JFrameを半透明化>Swing/WindowOpacity]] -- `JFrame.setDefaultLookAndFeelDecorated(true); JFrame#setBackground(new Color(0x0, true));`などで`JFrame`を半透明化する場合は`SystemLookAndFeel`などで使用不可、また`ConvolveOp`などを適用してぼかし効果なども不可となる - [https://stackoverflow.com/questions/70234904/how-to-make-the-jframe-contentpane-transparent-but-the-jframe-visible java - How to make the JFrame contentPane transparent but the JFrame visible? - Stack Overflow] * コメント [#comment] #comment #comment