【问题标题】:Create rectangle with mouse drag, not draw用鼠标拖动创建矩形,而不是绘制
【发布时间】:2013-04-02 23:54:20
【问题描述】:

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

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

【问题讨论】:

    标签: java awt screenshot


    【解决方案1】:

    nb- 首先要注意,这是使用 Java 7 完成的,在 Java 6 中创建透明窗口的方式有所不同,并且在更新 10 之后是不可能的(我相信)

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

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

    面板是透明的。这允许面板(和框架)下方的任何内容保持可见。然后,我用透明颜色对其进行了过度绘制(我这样做只是为了突出这一事实)。

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

    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");
    }
    

    使用替代方法更新

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

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

    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 7?除了当我拖动矩形时,矩形内部的颜色仍然是透明 jframe 的颜色之外,似乎我已经在 J​​ava6 上完成了所有工作。我设法使用 AWTUtilities.setWindowOpacity(capture ,(float)0.40); 将 JFrame 设置为透明
    • 我会改用AWTUtilities.setWindowOpaque(frame, false);,你希望窗口是透明的,而不是半透明的;)
    • 这个frame.setBackground(new Color(0, 0, 0, 0)); 是在Java 7 中实现同样的事情的方式
    • 现在拖动它,它将打开一个选择区域。如果您想以另一种方式进行操作,则有一个技巧,基本上是您拍摄屏幕截图并将其绘制到窗口的背景上(这就是 Windows 中的 snip it 工具的工作方式)并允许用户拖动一个矩形上面的区域。试图获得一个可以从无到有(当它是透明的)拖动到大小的窗口是非常困难的
    • 嗯...它下面似乎没有显示任何东西...我猜用户只需要 Java 7 :/ 感谢您的帮助!还有什么我可以做的吗?
    【解决方案2】:

    您可以考虑创建一个透明的全屏 JFrame。不过,这不是一个理想的技术。

    您可以查看this 以开始真正的解决方案。

    【讨论】:

    • 不用全屏独占模式,简单的让屏幕占据虚拟全屏
    • 好的,那我的制作矩形问题呢?
    猜你喜欢
    • 1970-01-01
    • 2014-10-14
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    相关资源
    最近更新 更多