Внутреннее отсечение с помощью Java Graphics - PullRequest
9 голосов
/ 07 августа 2009

Мне нужно нарисовать линию, используя java.awt.Graphics, но следует визуализировать только часть линии, которая находится за пределами прямоугольника.

Можно ли использовать поддержку отсечения графики или мне нужно самостоятельно рассчитать пересечение и обрезать линию?

Ответы [ 2 ]

10 голосов
/ 07 августа 2009

Вам необходимо использовать класс Площадь . Этот пример продемонстрирует, как сделать то, что вы просите:

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

}
3 голосов
/ 07 августа 2009

Вы можете сделать это с помощью клипа AWT. Вам нужно знать границы прямоугольника, который вы хотите исключить, и внешние границы области рисования.

Следующий демонстрационный код открывает рамку и отображает в ней одну панель. Метод рисования на панели устанавливает пример клипа, который выглядит как прямоугольник с прямоугольным отверстием посередине, тогда как на самом деле это многоугольник, который описывает область вокруг области, которую мы хотим исключить. Прямоугольник клипа должен состоять из границ исключенного прямоугольника и внешнего края области рисования, но я оставил жестко закодированные значения, чтобы сделать его простым и лучше проиллюстрировать работу (надеюсь!)

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

Этот метод имеет преимущество перед вычислением пересечения линий вручную в том смысле, что он предотвращает прохождение всей окраски AWT в исключаемую область. Я не знаю, полезно ли это вам или нет.

Затем моя демонстрация закрашивает черный прямоугольник по всей области, и через него проходит одна белая диагональная линия, чтобы проиллюстрировать работу клипа.

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