Criar retângulo com o mouse arrastado, não desenhar

Eu quero criar um retângulo usando a canvas inteira. Ao usar a canvas inteira, quero dizer algo assim:

Desktop como visto pelo usuário

Para começar, isso é possível mesmo em Java, usando a canvas inteira assim? Segundo, como eu faria isso? Outra coisa, eu não quero desenhar um retângulo real, eu quero criar, como em um novo java.awt.Rectangle .

Nota: Primeira coisa a notar, isso é feito usando o Java 7, criando uma janela transparente no Java 6 é feito de forma diferente e não é possível abaixo da atualização 10 (eu acredito)

Basicamente, isso cria uma janela transparente, dimensionada e posicionada para cobrir toda a canvas virtual (ou seja, se você tiver várias canvass, ela abrangerá todas elas).

Em seguida, uso um JPanel como o contêiner principal para capturar events de mouse e executar efeitos de pintura.

O painel é transparente. Isso permite que o que estiver abaixo do painel (e do quadro) permaneça visível. Eu já pintei isso com uma cor transparente (eu fiz isso apenas para destacar o fato).

Quando você clica e arrasta uma área, ela é exposta.

insira a descrição da imagem aqui

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

Da mesma forma, você pode simplesmente criar um quadro transparente que o usuário possa resize. Você será responsável por implementar todo o código de redimensionamento sozinho, mas a solução ainda será viável.

Atualizada

Você também pode precisar verificar se o sistema operacional / hardware pode suportar a transparência …

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

Atualizado com abordagem alternativa

Esta é uma abordagem alternativa para o problema. Basicamente, é preciso tirar uma foto da canvas e renderiza para a janela. Isso nos permite controlar o realce / seleção conforme necessário.

A desvantagem disso é que é um resultado estático, você não terá nenhum efeito de animação em execução no momento.

insira a descrição da imagem aqui

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

Você poderia procurar criar um JFrame em canvas cheia transparente. Isso não seria uma técnica ideal.

Você pode dar uma olhada nisso para começar uma solução real.