绘制具有给定厚度,位置和半径的环。 (的Java2D)

时间:2016-02-20 14:09:19

标签: java swing graphics2d java-2d ellipse

我需要绘制一个具有给定厚度的环,看起来像这样:

enter image description here

中心必须是透明的,以便它不会覆盖以前绘制的形状。 (或其他戒指)我尝试过这样的事情:

//g is a Graphics2D object
g.setColor(Color.RED);
g.drawOval(x,y,width,height);
g.setColor(Color.WHITE);
g.drawOval(x+thickness,y+thickness,width-2*thickness,height-2*thickness);

它绘制了一个令人满意的戒指,但它涵盖了其他形状;内部是白色的,不透明。如何修改/重写我的代码,使其不这样做?

3 个答案:

答案 0 :(得分:8)

您可以从Area创建描述外圈的Ellipse2D,以及subtract描述内圈的椭圆。这样,您将获得可以Shapedrawn的实际filled(这只会引用环实际覆盖的区域!)。

优点是你确实可以使用戒指的几何。例如,这允许您检查环形contains是否为某一点,或者用Paint填充多于一种颜色:

RingPaint01

以下是一个示例,相关部分是createRingShape方法:

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;

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

public class RingPaintTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        RingPaintTestPanel p = new RingPaintTestPanel();
        f.getContentPane().add(p);
        f.setSize(800,800);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}


class RingPaintTestPanel extends JPanel
{
    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;

        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        g.setColor(Color.RED);
        g.drawString("Text", 100, 100);
        g.drawString("Text", 300, 100);

        Shape ring = createRingShape(100, 100, 80, 20); 
        g.setColor(Color.CYAN);
        g.fill(ring);
        g.setColor(Color.BLACK);
        g.draw(ring);

        Shape otherRing = createRingShape(300, 100, 80, 20); 
        g.setPaint(new GradientPaint(
            new Point(250, 40), Color.RED, 
            new Point(350, 200), Color.GREEN));
        g.fill(otherRing);
        g.setColor(Color.BLACK);
        g.draw(otherRing);

    }

    private static Shape createRingShape(
        double centerX, double centerY, double outerRadius, double thickness)
    {
        Ellipse2D outer = new Ellipse2D.Double(
            centerX - outerRadius, 
            centerY - outerRadius,
            outerRadius + outerRadius, 
            outerRadius + outerRadius);
        Ellipse2D inner = new Ellipse2D.Double(
            centerX - outerRadius + thickness, 
            centerY - outerRadius + thickness,
            outerRadius + outerRadius - thickness - thickness, 
            outerRadius + outerRadius - thickness - thickness);
        Area area = new Area(outer);
        area.subtract(new Area(inner));
        return area;
    }

}

答案 1 :(得分:6)

您可以使用Areaimport java.awt.*; import javax.swing.*; import java.awt.geom.*; import java.net.*; public class Subtract extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int size = 100; int thickness = 10; int innerSize = size - (2 * thickness); Shape outer = new Ellipse2D.Double(0, 0, size, size); Shape inner = new Ellipse2D.Double(thickness, thickness, innerSize, innerSize); Area circle = new Area( outer ); circle.subtract( new Area(inner) ); int x = (getSize().width - size) / 2; int y = (getSize().height - size) / 2; g2d.translate(x, y); g2d.setColor(Color.CYAN); g2d.fill(circle); g2d.setColor(Color.BLACK); g2d.draw(circle); g2d.dispose(); } private static void createAndShowGUI() { JFrame frame = new JFrame("Subtract"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new Subtract()); frame.setLocationByPlatform( true ); frame.setSize(200, 200); frame.setVisible( true ); } public static void main(String[] args) { EventQueue.invokeLater( () -> createAndShowGUI() ); /* EventQueue.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); */ } } 类创建有趣的效果:

[]

使用区域,您还可以将多个形状一起添加或获取多个形状的交集。

答案 2 :(得分:3)

您可以使用graphics.setStroke(...)。这样,中心将完全透明,因此不会覆盖以前绘制的形状。在我的示例中,由于此方法,我不得不进行一些额外的计算,以确保显示的xy坐标实际上与Ring实例的坐标相同:< / p>

enter image description here

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.util.ArrayList;

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

public class Example {

    public Example() {
        ArrayList<Ring> rings = new ArrayList<Ring>();
        rings.add(new Ring(10, 10, 100, 20, Color.CYAN));

        JPanel panel = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D gg = (Graphics2D) g.create();
                gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                for (Ring ring : rings) {
                    // Previously drawn
                    gg.setColor(Color.BLACK);
                    String str = "Hello!";
                    gg.drawString(str, ring.getX() + (ring.getWidth() - gg.getFontMetrics().stringWidth(str)) / 2,
                            ring.getY() + ring.getHeight() / 2 + gg.getFontMetrics().getAscent());

                    // The actual ring
                    ring.draw(gg);
                }

                gg.dispose();
            }
        };

        JFrame frame = new JFrame();
        frame.setContentPane(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Example();
            }
        });
    }

}

class Ring {
    private int x, y, width, height, thickness;
    private Color color;

    public Ring(int x, int y, int width, int height, int thickness, Color color) {
        setX(x);
        setY(y);
        setWidth(width);
        setHeight(height);
        setThickness(thickness);
        setColor(color);
    }

    public Ring(int x, int y, int radius, int thickness, Color color) {
        this(x, y, radius * 2, radius * 2, thickness, color);
    }

    public void draw(Graphics2D gg) {
        Stroke oldStroke = gg.getStroke();
        Color oldColor = gg.getColor();

        gg.setColor(Color.BLACK);
        gg.setStroke(new BasicStroke(getThickness()));
        gg.drawOval(getX() + getThickness() / 2, getY() + getThickness() / 2, getWidth() - getThickness(),
                getHeight() - getThickness());
        gg.setColor(getColor());
        gg.setStroke(new BasicStroke(getThickness() - 2));
        gg.drawOval(getX() + getThickness() / 2, getY() + getThickness() / 2, getWidth() - getThickness(),
                getHeight() - getThickness());

        gg.setStroke(oldStroke);
        gg.setColor(oldColor);
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getThickness() {
        return thickness;
    }

    public void setThickness(int thickness) {
        this.thickness = thickness;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

}