2009-08-06 14 views
9

Ho bisogno di disegnare una linea usando java.awt.Graphics, ma solo la porzione della linea che si trova al di fuori di un rettangolo deve essere visualizzata.Dentro il clipping con Java Graphics

È possibile utilizzare il supporto di ritaglio della grafica o devo calcolare l'intersezione e ritagliare la linea da solo?

risposta

10

È necessario utilizzare la classe Area. Questo esempio mostrerà come fare quello che chiedi:

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

Grazie, perfetto! – tuler

+1

+1 - Molto meglio del mio :) – banjollity

+0

Il metodo Area è migliore in termini di leggibilità ed estensibilità (è possibile creare qualsiasi forma e clip al suo esterno) ma penso che potrebbe avere alcuni problemi di prestazioni (la classe Area è un po ' sopra le righe forse). Dovresti fare un benchmark se devi disegnare sulla clip molte volte e vedere se l'altro metodo è più veloce. –

3

È possibile eseguire questa operazione con una clip AWT. Dovrai conoscere i limiti del rettangolo che desideri escludere e i limiti esterni dell'area di disegno.

Il seguente codice demo apre una cornice e visualizza un pannello singolo al suo interno. Il metodo paint del pannello imposta una clip di esempio che assomiglia ad un rettangolo con un buco rettangolare nel mezzo, quando in realtà è un poligono che descrive l'area intorno all'area che vogliamo escludere. Il rettangolo della clip dovrebbe essere composto dai limiti del rettangolo escluso e dal bordo esterno dell'area di disegno, ma ho lasciato i valori codificati per mantenerlo semplice e illustrare meglio il funzionamento (spero!)

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

Questo metodo ha il vantaggio di calcolare manualmente l'intersezione della linea in quanto impedisce a tutti i dipinti AWT di entrare nell'area esclusa. Non so se ti è utile o no.

La mia demo dipinge quindi un rettangolo nero sull'intera area e una singola linea diagonale bianca che la attraversa, per illustrare il funzionamento della 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

Anche corretto. Ma l'altro è più facile perché usa sottrarre. Grazie. – tuler

+0

Sì, la risposta di Savvas Dalkitsis è molto meglio. – banjollity

+0

+1. Questa risposta funziona quasi e utilizza le API supportate da J2ME PP. Ho scoperto che dovevo iniziare la forma a 0,20 per creare un poligono chiuso. Il codice completo funziona nella mia domanda: http://stackoverflow.com/questions/1273688/is-there-any-way-to-have-an-inverted-clip-region-for-painting-in-java –