java - 用鼠标拖动创建矩形,而不是绘制

标签 java awt screenshot

我想使用整个屏幕创建一个矩形。通过使用整个屏幕,我的意思是这样的:

Desktop as seen by user

首先,在 Java 中是否可以像那样使用整个屏幕?其次,我将如何着手去做?另一件事,我不想绘制一个实际的矩形,我想创建一个新的 java.awt.Rectangle

最佳答案

nb- 首先要注意,这是使用 Java 7 完成的,在 Java 6 中创建透明窗口的方式不同,在 update 10 以下是不可能的(我相信)

基本上,这会创建一个透明窗口,其大小和位置可以覆盖整个虚拟屏幕(也就是说,如果您有多个屏幕,它将覆盖所有屏幕)。

然后我使用 JPanel 作为主要容器来捕获鼠标事件并执行绘画效果。

面板是透明的。这允许面板(和框架)下方的内容保持可见。然后我用透明颜色覆盖了它(我这样做只是为了突出事实)。

当您点击并拖动一个区域时,它会暴露出来。

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MySnipTool {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setUndecorated(true);
                frame.setBackground(new Color(0, 0, 0, 0));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new CapturePane());
                Rectangle bounds = getVirtualBounds();
                frame.setLocation(bounds.getLocation());
                frame.setSize(bounds.getSize());
                frame.setAlwaysOnTop(true);
                frame.setVisible(true);
            }
        });
    }

    public class CapturePane extends JPanel {

        private Rectangle selectionBounds;
        private Point clickPoint;

        public CapturePane() {
            setOpaque(false);

            MouseAdapter mouseHandler = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
                        System.exit(0);
                    }
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    clickPoint = e.getPoint();
                    selectionBounds = null;
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    clickPoint = null;
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    Point dragPoint = e.getPoint();
                    int x = Math.min(clickPoint.x, dragPoint.x);
                    int y = Math.min(clickPoint.y, dragPoint.y);
                    int width = Math.max(clickPoint.x - dragPoint.x, dragPoint.x - clickPoint.x);
                    int height = Math.max(clickPoint.y - dragPoint.y, dragPoint.y - clickPoint.y);
                    selectionBounds = new Rectangle(x, y, width, height);
                    repaint();
                }
            };

            addMouseListener(mouseHandler);
            addMouseMotionListener(mouseHandler);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(new Color(255, 255, 255, 128));

            Area fill = new Area(new Rectangle(new Point(0, 0), getSize()));
            if (selectionBounds != null) {
                fill.subtract(new Area(selectionBounds));
            }
            g2d.fill(fill);
            if (selectionBounds != null) {
                g2d.setColor(Color.BLACK);
                g2d.draw(selectionBounds);
            }
            g2d.dispose();
        }
    }

    public static Rectangle getVirtualBounds() {
        Rectangle bounds = new Rectangle(0, 0, 0, 0);

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice lstGDs[] = ge.getScreenDevices();
        for (GraphicsDevice gd : lstGDs) {
            bounds.add(gd.getDefaultConfiguration().getBounds());
        }
        return bounds;
    }
}

同样,您可以只创建一个用户可以调整大小的透明框架。您将负责自己实现所有调整大小的代码,但该解决方案仍然是可行的。

已更新

您可能还需要检查操作系统/硬件是否可以支持透明度...

GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
if (!AWTUtilities.isTranslucencyCapable(config)) {
    System.out.println("Transluceny is not supported");
}

if (!AWTUtilities.isTranslucencySupported(AWTUtilities.Translucency.PERPIXEL_TRANSPARENT)) {
    System.out.println("PerPeixel Transparency is not supported");
}

更新了替代方法

这是解决该问题的另一种方法。基本上它拍摄屏幕快照并将其呈现到窗口。这样我们就可以根据需要控制突出显示/选择。

这样做的缺点是它是静态结果,您不会获得任何当前正在运行的动画效果。

enter image description here

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SnipWithScreenShoot {

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

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

                try {
                    JFrame frame = new JFrame("Test");
                    frame.setUndecorated(true);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (AWTException exp) {
                    exp.printStackTrace();
                    System.out.println("That sucks");
                }
            }

        });
    }

    public class TestPane extends JPanel {

        private BufferedImage image;
        private Rectangle selection;

        public TestPane() throws AWTException {
            Robot bot = new Robot();
            image = bot.createScreenCapture(getVirtualBounds());

            MouseAdapter handler = new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    selection = new Rectangle(e.getPoint());
                    repaint();
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    Point p = e.getPoint();
                    int width = Math.max(selection.x - e.getX(), e.getX() - selection.x);
                    int height = Math.max(selection.y - e.getY(), e.getY() - selection.y);
                    selection.setSize(width, height);
                    repaint();
                }
            };

            addMouseListener(handler);
            addMouseMotionListener(handler);
        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (image != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(image, WIDTH, 0, this);
                if (selection != null) {
                    g2d.setColor(new Color(225, 225, 255, 128));
                    g2d.fill(selection);
                    g2d.setColor(Color.GRAY);
                    g2d.draw(selection);
                }
                g2d.dispose();
            }
        }

    }

    public static Rectangle getVirtualBounds() {

        Rectangle bounds = new Rectangle(0, 0, 0, 0);

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice lstGDs[] = ge.getScreenDevices();
        for (GraphicsDevice gd : lstGDs) {

            bounds.add(gd.getDefaultConfiguration().getBounds());

        }

        return bounds;

    }

}

关于java - 用鼠标拖动创建矩形,而不是绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15776549/

相关文章:

java - Spring MVC 一个 href 重定向到另一个 JSP

java - 这是在单独线程上删除文件夹的正确方法吗?

java - 将 jar 上的本地 html 文件加载到 Web 引擎中

java - 使用 AWT 和 Java 组件进行绘图

java - 在椭圆上画线

java - 有没有办法在使用java锁定窗口时获取屏幕截图?

java - 计算复杂度时是: does a[0] + a[1] result in two array accesses,还是只有一个?

screenshot - 与屏幕截图相关的 Itunes Connect 问题

delphi - 如何在Delphi中截取事件窗口的屏幕截图?

java - Graphics2D - 在所有平台上呈现相同的文本