如何填写两个Line2D.Double?

时间:2017-01-20 03:07:43

标签: java graphics shapes

您好我正在尝试为我的应用创建 heart 形状 我可以做空心的,它工作得很好,现在我需要用填充方法绘制它,但它是由两个Arc2D.Double和两个Line2D.Double创建的,所以因为这只是Arc的填充和两条线没有。我试过了将这两行添加到两个不同的“区域”中,并将这两个区域添加到一个区域中,但也不起作用。

有任何方法可以做到这一点(在两行之间填写)?谢谢提前。

我的代码: Class Heart

`public class HeartShape {

    private ArrayList<Shape> shapes;
    public HeartShape() {

    }

    public ArrayList<Shape> Heart(double x, double y, double HEART_RADIUS) {
        shapes = new ArrayList<>();
        double r = HEART_RADIUS;
        double root2 = Math.sqrt(2);
        double cx = x;
        double cy = y;
        double dx = r / root2;
        double heights = 3 * dx + r;
        double top = cy - heights / 2;
        double bottom = cy + heights / 2;
        Shape s = new Arc2D.Double(cx - dx - r, top, 2 * r, 2 * r, 45, 180, Arc2D.OPEN);
        shapes.add(s);
        s = new Arc2D.Double(cx + dx - r, top, 2 * r, 2 * r, -45, 180, Arc2D.OPEN);
        shapes.add(s);
        s = new Line2D.Double(cx, bottom, cx - 2 * dx, bottom - 2 * dx);
        shapes.add(s);
        s = new Line2D.Double(cx, bottom, cx + 2 * dx, bottom - 2 * dx);
        shapes.add(s);
        if (shapes != null) {
            return shapes;
        } else {
            return null;
        }
    }

    public void drawHeart(Graphics2D g2d, boolean isFilled) {

        if (isFilled == true) {
                    shapes.forEach((ss) -> {
                        g2d.fill(ss);
                    });
        } else {
                    shapes.forEach((ss) -> {
                        g2d.draw(ss);
                    });
        }

    }`

DrawinTest

public class DrawinTest extends JPanel{
private int HEART_RADIUS;
private Point startpoint;
private int x, y, width, height;
private HeartShape heartShape = new HeartShape();
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    new DrawinTest();
}

public DrawinTest() {
    JFrame f = new JFrame("Test Area");
    f.setPreferredSize(new Dimension(600, 500));
    f.setLocationRelativeTo(null);
    f.setLayout(new BorderLayout(0, 1));
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.addMouseListener(new MyMouseListener());
    this.addMouseMotionListener(new MyMouseListener());
    this.setBackground(Color.WHITE);
    f.setContentPane(this);
    f.setVisible(true);
    f.pack();
}

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

    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setStroke(new BasicStroke(3));
    g2d.setColor(Color.RED);

    if(heartShape != null) {
        heartShape.Heart(x, y, HEART_RADIUS);
        heartShape.drawHeart(g2d, false);

    }
   g2d.dispose();
}

class MyMouseListener implements MouseListener,MouseMotionListener {

    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {
        startpoint = new Point(e.getPoint());
    }

    @Override
    public void mouseReleased(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

    @Override
    public void mouseDragged(MouseEvent e) {
        x = Math.min(startpoint.x, e.getX());
        y = Math.min(startpoint.y, e.getY());
        width = Math.abs(startpoint.x - e.getX());
        height = Math.abs(startpoint.y - e.getY());
        HEART_RADIUS = Math.min(width, height);
        repaint();
    }

    @Override
    public void mouseMoved(MouseEvent e) {}

   }
}

到目前为止看起来像这样:

Empty Filled

2 个答案:

答案 0 :(得分:2)

Shape的API有许多非常有趣的API,我的最爱之一是Path2D

基本上,它允许你做的是附加其他Shape,使其在这种情况下非常有用。

public class HeartShape {

    private Shape shape;

    public HeartShape() {

    }

    public Shape Heart(double x, double y, double HEART_RADIUS) {
        double r = HEART_RADIUS;
        double root2 = Math.sqrt(2);
        double cx = x;
        double cy = y;
        double dx = r / root2;
        double heights = 3 * dx + r;
        double top = cy - heights / 2;
        double bottom = cy + heights / 2;

        Path2D base = new Path2D.Double();
        Shape s = new Arc2D.Double(cx - dx - r, top, 2 * r, 2 * r, 45, 180, Arc2D.OPEN);
        base.append(s, false);
        s = new Line2D.Double(cx, bottom, cx - 2 * dx, bottom - 2 * dx);
        base.append(s, true);
        s = new Line2D.Double(cx, bottom, cx + 2 * dx, bottom - 2 * dx);
        base.append(s, true);
        s = new Arc2D.Double(cx + dx - r, top, 2 * r, 2 * r, -45, 180, Arc2D.OPEN);
        base.append(s, true);

        base.closePath();

        shape = base;

        return base;
    }

    public void drawHeart(Graphics2D g2d, boolean isFilled) {
        System.out.println("...");
        if (isFilled) {
            g2d.fill(shape);
        } else {
            g2d.draw(shape);
        }
    }
}

this example所示,当你想要改变它的大小时,你不需要重新创建形状,你可以简单地创建一个“默认”大小的实例并使用{{ 1}}调整它的大小,更容易;)

答案 1 :(得分:1)

我认为不是使用shapeList的数组,而是使用GenericPath并使用GenericPath.append()将每个单独的形状附加到它。你完成的一件事就是添加心脏使用部分GenericPath.closePath(),使它紧密结束,以便它可以被填充。然后,您应该能够使用新的GenericPath对象作为使用g2d.draw

绘制的路径