2009-08-06 27 views
9

Necesito dibujar una línea usando java.awt.Graphics, pero solo debe representarse la parte de la línea que se encuentra fuera de un rectángulo.Recorte interno con Java Graphics

¿Es posible utilizar el soporte de recorte Gráficos o necesito calcular la intersección y cortar la línea yo mismo?

Respuesta

10

Debe utilizar la clase Area. Este ejemplo demostrará cómo hacer lo que pregunta:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.geom.Area; 
import java.awt.geom.Rectangle2D; 

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


public class Test extends JPanel { 

    public static void main(String[] args) { 
     JFrame f = new JFrame(); 
     Test t = new Test(); 
     f.getContentPane().setLayout(new BorderLayout()); 
     f.getContentPane().add(t,BorderLayout.CENTER); 
     f.pack(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setVisible(true); 
    } 

    public Test() { 
     setPreferredSize(new Dimension(300, 300)); 
    } 

    public void paintComponent(Graphics g) { 
     Graphics2D g2 = (Graphics2D)g.create(); 
     Rectangle2D rectangleNotToDrawIn = new Rectangle2D.Double(100, 100, 20, 30); 
     Area outside = calculateRectOutside(rectangleNotToDrawIn); 
     g2.setPaint(Color.white); 
     g2.fillRect(0, 0, getWidth(), getHeight()); 
     g2.setPaint(Color.black); 
     g2.setClip(outside); 
     g2.drawLine(0, 0, getWidth(), getHeight()); 

    } 


    private Area calculateRectOutside(Rectangle2D r) { 
     Area outside = new Area(new Rectangle2D.Double(0, 0, getWidth(), getHeight())); 
     outside.subtract(new Area(r)); 
     return outside; 
    } 

} 
+0

Gracias, perfecto! – tuler

+1

+1 - Mucho mejor que el mío :) – banjollity

+0

El método del Área es mejor en términos de legibilidad y extensibilidad (puede crear cualquier forma y clip en su exterior) pero creo que podría tener algunos problemas de rendimiento (la clase Área es un poco sobre la cima tal vez). Debe compararlo si necesita dibujar en el clip muchas veces y ver si el otro método es más rápido. –

3

Puede hacerlo con un clip AWT. Deberá conocer los límites del rectángulo que desea excluir y los límites exteriores de su área de dibujo.

El siguiente código de demostración abre un marco y muestra un solo panel en él. El método de pintura del panel establece un clip de ejemplo que se parece a un rectángulo con un agujero rectangular en el centro, cuando de hecho es un polígono que describe el área alrededor del área que queremos excluir. El rectángulo del clip debe estar compuesto por los límites del rectángulo excluido y el borde exterior del área de dibujo, pero he dejado valores codificados para mantenerlo simple e ilustrar mejor el funcionamiento (¡espero!)

 
+-------------------+ 
| clip drawing area | 
+---+-----------+ | 
| | excluded | | 
| | area | | 
| +-----------+ | 
|     | 
+-------------------+ 

Este método tiene el beneficio sobre el cálculo manual de la intersección de líneas, ya que evita que todas las pinturas AWT entren en el área excluida. No sé si eso es útil para ti o no.

Mi demostración pinta un rectángulo negro en toda el área y una sola línea diagonal blanca que lo atraviesa, para ilustrar el funcionamiento del clip.

public class StackOverflow extends JFrame { 
    public static void main(String[] args) { 
     new StackOverflow(); 
    } 

    private StackOverflow() { 
     setTitle("Clip with a hole"); 
     setSize(320,300); 
     getContentPane().add(new ClipPanel()); 
     setVisible(true); 
    } 
} 

class ClipPanel extends JPanel { 
    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     Polygon clip = new Polygon(
       new int[]{ 0, 100, 100, 0, 0, 20, 20, 80, 80, 0 }, 
       new int[]{ 0, 0, 60, 60, 20, 20, 40, 40, 20, 20 }, 
       10 
      ); 
     g.setClip(clip); 
     g.setColor(Color.BLACK); 
     g.fillRect(0,0,100,60); 
     g.setColor(Color.WHITE); 
     g.drawLine(0,0,100,60); 
    } 
} 
+0

También corrija. Pero el otro es más fácil porque usa restar. Gracias. – tuler

+0

Sí, la respuesta de Savvas Dalkitsis es mucho mejor. – banjollity

+0

+1. Esta respuesta casi funciona, y usa API compatibles con J2ME PP. Descubrí que tenía que comenzar la forma en 0,20 para crear un polígono cerrado. El código de trabajo completo está en mi pregunta: http://stackoverflow.com/questions/1273688/is-there-any-way-to-have-an-inverted-clip-region-for-painting-in-java –