Robot.createScreenCapture()似乎与绘画操作不匹配

时间:2015-02-28 00:14:29

标签: java swing awtrobot

我试图让屏幕的一部分显得模糊。我从BufferedImage中抓取像素颜色,在那里我保存了屏幕捕获并再次将像素绘制为更大的方块。但这仅在第一次调用paint方法时有效,之后即使屏幕内容更新,受影响的像素也始终保持不变。因此,即使画布在绘制方法的开头刷新,机器人仍然可以像以前一样看到屏幕......

@Override public void paintComponent(Graphics g) {
    super.paintComponent(g);

    screen = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));

    int gap = 10; int width = 1920;
    for (int r = 120; r <= 420; r += gap) {
        for (int c = 500; c <= width - 500; c += gap) {
            g.setColor(new Color(screen.getRGB(c, r)));
            g.fillRect(c, r, gap, gap);
        }
    }
}

我尝试使用clearRect()清除绘制区域并在不同位置睡眠线程,但它没有工作。我需要在哪里放置createScreenCapture()以便绘画实际更新?

这是全班:

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Transparent extends JPanel implements Runnable {
    private JFrame frame;
    private Robot robot;
    private BufferedImage screen;

public static void main(String[] args) {
    new Transparent();
}

public Transparent() {
    try {
        robot = new Robot();
    } catch (AWTException ex) {
        ex.printStackTrace();
    }

    frame = new JFrame();
    init();
    frame.add(this);
    frame.setUndecorated(true);
    frame.setBackground(new Color(0, true));
    frame.setAlwaysOnTop(true);
    frame.setSize(1920, 1080);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setVisible(true);

    new Thread(this).start();
}

public void init() {
    setBackground(new Color(0, true));
    setOpaque(false);
}

@Override public void paintComponent(Graphics g) {
    super.paintComponent(g);

    screen = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));

    int gap = 5; int width = 1920;
    for (int r = 120; r <= 420; r += gap) {
        for (int c = 500; c <= width - 500; c += gap) {
            g.setColor(new Color(screen.getRGB(c, r)));
            g.fillRect(c, r, gap, gap);
        }
    }
}

@Override public void run() {
    while (true) {
        repaint();

        try {
            Thread.sleep(10);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

}

1 个答案:

答案 0 :(得分:0)

我身上出现了很多东西......

  • 您似乎正在捕捉谁的屏幕,但是如果窗口可能实际定位以及它可能覆盖的区域,则不会考虑
  • 当您捕获屏幕时,您的组件将会在其上...

现在,这是一个非常简单的例子。我演示了如何将面板区域转换为屏幕坐标并仅捕获该区域。它通过首先隐藏窗口,然后在重新显示窗口并绘制生成的快照之前拍摄它的快照来实现这一点......

Snapshot

import com.jhlabs.image.GaussianFilter;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Transparency;
import java.awt.Window;
import java.awt.event.HierarchyBoundsAdapter;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                try {
                    JPanel outter = new JPanel(new BorderLayout());
                    outter.setBorder(new EmptyBorder(20, 20, 20, 20));
                    outter.add(new TestPane());

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(outter);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (AWTException | HeadlessException exp) {
                    exp.printStackTrace();
                }

            }
        });
    }

    public class TestPane extends JPanel {

        private Robot bot;
        private BufferedImage snapShot;
        private Point lastSnapShot;

        public TestPane() throws AWTException {
            bot = new Robot();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        public void updateSnapshot() {

            Rectangle bounds = getBounds();
            Point p = new Point(0, 0);
            SwingUtilities.convertPointToScreen(p, this);
            bounds.setLocation(p);

            if (lastSnapShot == null || !lastSnapShot.equals(p)) {

                lastSnapShot = p;
                Window window = SwingUtilities.getWindowAncestor(this);

                window.addHierarchyListener(new HierarchyListener() {
                    @Override
                    public void hierarchyChanged(HierarchyEvent e) {
                        if (!window.isVisible()) {
                            e.getComponent().removeHierarchyListener(this);

                            snapShot = bot.createScreenCapture(bounds);
                            snapShot = generateBlur(snapShot, 10);

                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    window.setVisible(true);
                                }
                            });
                        }
                    }
                });
                window.setVisible(false);
            }

        }

        public BufferedImage generateBlur(BufferedImage imgSource, int size) {

            GaussianFilter filter = new GaussianFilter(size);

            int imgWidth = imgSource.getWidth();
            int imgHeight = imgSource.getHeight();

            BufferedImage imgBlur = createCompatibleImage(imgWidth, imgHeight, Transparency.OPAQUE);
            Graphics2D g2 = imgBlur.createGraphics();

            g2.drawImage(imgSource, 0, 0, null);
            g2.dispose();

            imgBlur = filter.filter(imgBlur, null);

            return imgBlur;

        }

        public BufferedImage createCompatibleImage(int width, int height, int transparency) {

            GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();

            BufferedImage image = gc.createCompatibleImage(width, height, transparency);
            image.coerceData(true);
            return image;

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (snapShot == null) {
                updateSnapshot();
            }
            int x = 0;
            int y = 0;
            g2d.drawImage(snapShot, 0, 0, this);
            g2d.dispose();
        }

    }

}

此示例利用了JH Lab's Filters,因为我懒得创建自己的...