2012-12-19 3 views
7

boundein Begrenzungsrechteck Zeichnung zu wählen, welcher Bereich

aufnehmen, wie ich die halbtransparente Rechteck auf dem Bildschirm zeichne? Das kann kein JFrame sein, weil JFrames die üblichen Optionen zum Schließen, Minimieren, Maximieren oben rechts haben.
Wenn es in der Tat ein Schwungkompetent ist, wie wird es in dünner Luft gezeichnet? Ohne es in eine JFrame einfügen? Bitte sagen Sie mir, was es ist und wie ich es implementieren kann ...

+1

Dieses Tutorial könnte helfen Ihnen, [wie transparente Fenster machen] (http://docs.oracle.com/ javase/tutorial/uiswing/misc/trans_shaped_windows.html) –

Antwort

9

Die unmittelbare Idee, die in den Sinn kommt, ist java.awt.Robot zu verwenden, um einen Screenshot zu erfassen, das zu rahmenlosen Fenster zu malen. Von dort können Sie einfach ein Rechteck zeichnen auf sie

mit Beispiel aktualisiert

... dauerte einige Zeit, ...

enter image description here

public class SelectionRectangle { 

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

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

       JFrame frame = new JFrame("Test"); 
       frame.setUndecorated(true); 
       frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new BackgroundPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

     }); 
    } 

    public class BackgroundPane extends JPanel { 

     private BufferedImage background; 
     private Point mouseAnchor; 
     private Point dragPoint; 

     private SelectionPane selectionPane; 

     public BackgroundPane() { 
      selectionPane = new SelectionPane(); 
      try { 
       Robot bot = new Robot(); 
       background = bot.createScreenCapture(getScreenViewableBounds()); 
      } catch (AWTException ex) { 
       Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      selectionPane = new SelectionPane(); 
      setLayout(null); 
      add(selectionPane); 

      MouseAdapter adapter = new MouseAdapter() { 
       @Override 
       public void mousePressed(MouseEvent e) { 
        mouseAnchor = e.getPoint(); 
        dragPoint = null; 
        selectionPane.setLocation(mouseAnchor); 
        selectionPane.setSize(0, 0); 
       } 

       @Override 
       public void mouseDragged(MouseEvent e) { 
        dragPoint = e.getPoint(); 
        int width = dragPoint.x - mouseAnchor.x; 
        int height = dragPoint.y - mouseAnchor.y; 

        int x = mouseAnchor.x; 
        int y = mouseAnchor.y; 

        if (width < 0) { 
         x = dragPoint.x; 
         width *= -1; 
        } 
        if (height < 0) { 
         y = dragPoint.y; 
         height *= -1; 
        } 
        selectionPane.setBounds(x, y, width, height); 
        selectionPane.revalidate(); 
        repaint(); 
       } 

      }; 
      addMouseListener(adapter); 
      addMouseMotionListener(adapter); 

     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.drawImage(background, 0, 0, this); 
      g2d.dispose(); 
     } 

    } 

    public class SelectionPane extends JPanel { 

     private JButton button; 
     private JLabel label; 

     public SelectionPane() { 
      button = new JButton("Close"); 
      setOpaque(false); 

      label = new JLabel("Rectangle"); 
      label.setOpaque(true); 
      label.setBorder(new EmptyBorder(4, 4, 4, 4)); 
      label.setBackground(Color.GRAY); 
      label.setForeground(Color.WHITE); 
      setLayout(new GridBagLayout()); 

      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      add(label, gbc); 

      gbc.gridy++; 
      add(button, gbc); 

      button.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        SwingUtilities.getWindowAncestor(SelectionPane.this).dispose(); 
       } 
      }); 

      addComponentListener(new ComponentAdapter() { 
       @Override 
       public void componentResized(ComponentEvent e) { 
        label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight()); 
       } 
      }); 

     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.setColor(new Color(128, 128, 128, 64)); 
      g2d.fillRect(0, 0, getWidth(), getHeight()); 

      float dash1[] = {10.0f}; 
      BasicStroke dashed = 
          new BasicStroke(3.0f, 
          BasicStroke.CAP_BUTT, 
          BasicStroke.JOIN_MITER, 
          10.0f, dash1, 0.0f); 
      g2d.setColor(Color.BLACK); 
      g2d.setStroke(dashed); 
      g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3); 
      g2d.dispose(); 
     } 

    } 

    public static Rectangle getScreenViewableBounds() { 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice gd = ge.getDefaultScreenDevice(); 

     return getScreenViewableBounds(gd); 
    } 

    public static Rectangle getScreenViewableBounds(GraphicsDevice gd) { 
     Rectangle bounds = new Rectangle(0, 0, 0, 0); 
     if (gd != null) { 
      GraphicsConfiguration gc = gd.getDefaultConfiguration(); 
      bounds = gc.getBounds(); 

      Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); 

      bounds.x += insets.left; 
      bounds.y += insets.top; 
      bounds.width -= (insets.left + insets.right); 
      bounds.height -= (insets.top + insets.bottom); 
     } 
     return bounds; 
    } 
} 

Aktualisierung mit SnipIt Beispiel

Einige Leute haben uns vorgeschlagen Wenn ein transparentes Fenster über den oberen Bildschirmrand gelegt wird, funktioniert dies nicht, da transparente Fenster nicht wirklich auf Mausklicks reagieren, es sei denn, sie haben etwas zu bemalen, mit dem das Mausereignis gefangen werden kann.

Es wurde auch vorgeschlagen, dass Sie ein Fenster als Auswahlmechanismus verwenden, dies ist eine gültige Antwort, aber ich würde (persönlich) finden, dass eine ungeeignete Lösung, wie Sie den Benutzer einfach klicken und ziehen möchten Auswahlrechteck (IMHO).

Ein anderer Ansatz ist etwas wie SnipIt zu verwenden.

enter image description here

public class SnipIt { 

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

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

       JFrame frame = new JFrame(); 
       frame.setUndecorated(true); 
       // This works differently under Java 6 
       frame.setBackground(new Color(0, 0, 0, 0)); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new SnipItPane()); 
       frame.setBounds(getVirtualBounds()); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class SnipItPane extends JPanel { 

     private Point mouseAnchor; 
     private Point dragPoint; 

     private SelectionPane selectionPane; 

     public SnipItPane() { 
      setOpaque(false); 
      setLayout(null); 
      selectionPane = new SelectionPane(); 
      add(selectionPane); 
      MouseAdapter adapter = new MouseAdapter() { 
       @Override 
       public void mousePressed(MouseEvent e) { 
        mouseAnchor = e.getPoint(); 
        dragPoint = null; 
        selectionPane.setLocation(mouseAnchor); 
        selectionPane.setSize(0, 0); 
       } 

       @Override 
       public void mouseDragged(MouseEvent e) { 
        dragPoint = e.getPoint(); 
        int width = dragPoint.x - mouseAnchor.x; 
        int height = dragPoint.y - mouseAnchor.y; 

        int x = mouseAnchor.x; 
        int y = mouseAnchor.y; 

        if (width < 0) { 
         x = dragPoint.x; 
         width *= -1; 
        } 
        if (height < 0) { 
         y = dragPoint.y; 
         height *= -1; 
        } 
        selectionPane.setBounds(x, y, width, height); 
        selectionPane.revalidate(); 
        repaint(); 
       } 
      }; 
      addMouseListener(adapter); 
      addMouseMotionListener(adapter); 
     } 

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

      Graphics2D g2d = (Graphics2D) g.create(); 

      Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight()); 
      Area area = new Area(bounds); 
      area.subtract(new Area(selectionPane.getBounds())); 

      g2d.setColor(new Color(192, 192, 192, 64)); 
      g2d.fill(area); 

     } 
    } 

    public class SelectionPane extends JPanel { 

     private JButton button; 
     private JLabel label; 

     public SelectionPane() { 
      button = new JButton("Close"); 
      setOpaque(false); 

      label = new JLabel("Rectangle"); 
      label.setOpaque(true); 
      label.setBorder(new EmptyBorder(4, 4, 4, 4)); 
      label.setBackground(Color.GRAY); 
      label.setForeground(Color.WHITE); 
      setLayout(new GridBagLayout()); 

      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      add(label, gbc); 

      gbc.gridy++; 
      add(button, gbc); 

      button.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        SwingUtilities.getWindowAncestor(SelectionPane.this).dispose(); 
       } 
      }); 

      addComponentListener(new ComponentAdapter() { 
       @Override 
       public void componentResized(ComponentEvent e) { 
        label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight()); 
       } 
      }); 

     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      // I've chosen NOT to fill this selection rectangle, so that 
      // it now appears as if you're "cutting" away the selection 
//   g2d.setColor(new Color(128, 128, 128, 64)); 
//   g2d.fillRect(0, 0, getWidth(), getHeight()); 

      float dash1[] = {10.0f}; 
      BasicStroke dashed = 
        new BasicStroke(3.0f, 
        BasicStroke.CAP_BUTT, 
        BasicStroke.JOIN_MITER, 
        10.0f, dash1, 0.0f); 
      g2d.setColor(Color.BLACK); 
      g2d.setStroke(dashed); 
      g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3); 
      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; 

    } 
} 
+0

Ja, 'Roboter' kann verwendet werden, um ** den Bildschirm zu erfassen **. und dann kann 'ImageIO' verwendet werden, um es auf die Festplatte zu schreiben, aber die Frage; Was ist das Geheimnis Rechteck? –

+0

Einfache Farbe auf das Bild mit Standard Graphics2D – MadProgrammer

+0

Ich glaube, die Frage bezieht sich auf die "Erfassungsbereich Grenze" auf dem Bildschirm selbst, anstatt das resultierende aufgenommene Bild (oder kann 'Robot' tatsächlich über JVM-Fenster gezeichnet werden?) – Vulcan

3

Sie einen transparenten, undecorated Rahmen, um eine grundlegende Grenze zu schaffen nutzen könnten.

public class ScreenRectangle extends JFrame { 

    public ScreenRectangle() { 
     this.setUndecorated(true); 
     this.setBackground(new Color(0, 0, 0, 0.25F)); 
     // opacity ranges 0.0-1.0 and is the fourth paramater 
     this.add(new DrawPanel()); 
    } 

    private class DrawPanel extends JPanel { 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.drawRect(0, 0, this.getWidth(), this.getHeight()); 
      // any other drawing 
     } 
    } 
} 

Der Rahmen kann auch setOpaque sein müssen, oder die Panel-Größe müssen behandelt werden, aber dies ist die allgemeine Vorstellung davon.

+0

Bitte rufen Sie 'super.paintComponent';) – MadProgrammer

+0

@MadProgrammer Hoppla! Das wurde behoben, danke. (Obwohl, wäre es in diesem Fall wirklich wichtig, weil sonst nichts auf dem JPanel gezeichnet wird? Vielleicht werde ich das später testen.) – Vulcan

+0

@Vulcan und es gibt keinen zusätzlichen Code erforderlich, um die veränderbare Größe richtig zu erstellen? 'JFrame' wird es selbst behandeln? –

7

Multi-Monitor-Unterstützung zum Beispiel aktualisieren Antwort von @MadProgrammer.

Ohne ExtendedState(JFrame.MAXIMIZED_BOTH) und pack()

enter image description here

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

      JFrame frame = new JFrame("Test"); 
      frame.setUndecorated(true); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setLayout(new BorderLayout()); 
      frame.add(new BackgroundPane()); 

      frame.setResizable(false); 
      frame.setBounds(getScreenViewableBounds()); 

      frame.setVisible(true); 
     } 

    }); 
} 

public static Rectangle getScreenViewableBounds() { 
    GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); 
    int minx = Integer.MAX_VALUE; 
    int miny = Integer.MAX_VALUE; 
    int maxx = Integer.MIN_VALUE; 
    int maxy = Integer.MIN_VALUE; 
    for(GraphicsDevice device : devices) { 
     for(GraphicsConfiguration config : device.getConfigurations()) { 
      Rectangle bounds = config.getBounds(); 
      minx = Math.min(minx, bounds.x); 
      miny = Math.min(miny, bounds.y); 
      maxx = Math.max(maxx, bounds.x + bounds.width); 
      maxy = Math.max(maxy, bounds.y + bounds.height); 
     } 
    } 
    return new Rectangle(new Point(minx, miny), new Dimension(maxx - minx, maxy - miny)); 
} 
+0

Das ist ein interessanter Ansatz. Ich würde einen Bereich in den getScreenViewableBounds verwenden, im Grunde jedes der Geräte Grenzen/Rechtecke zusammen, das bin nur ich – MadProgrammer

Verwandte Themen