Java drawing a RadialGradientPaint circle cut into a rectangle

Viewed 1868

I have the following code to draw a RadialGradientPaint circle:

public class Character {
    public static void draw(Graphics2D g2d){
        g2d.setColor(Color.RED);
        g2d.fillRect(0, 0, 1000, 750);
        drawVisibilityPolygon(g2d);
    }

    private static void drawVisibilityPolygon(Graphics2D g2d){
        Point center = new Point(1000 / 2, 750 / 2);
        float radius = 200;
        float[] dist = {
            0f,
            1f
        };
        Color[] colors = {
            new Color(0, 0, 0, 0),
            new Color(0, 0, 0, 255)
        };
        drawGradientCircle(g2d, radius, dist, colors, center);
    }

    private static void drawGradientCircle(Graphics2D g2d, float radius, float[] dist, Color[] colors, Point2D center){
        RadialGradientPaint rgp = new RadialGradientPaint(center, radius, dist, colors);
        g2d.setPaint(rgp);
        g2d.fill(new Ellipse2D.Double(center.getX() - radius, center.getY() - radius, radius * 2, radius * 2));
    }
}

The draw method is called by the Display class:

public class Display extends JPanel {
    @Override
    public void paintComponent(Graphics g){
        // SETUP
        BufferedImage base = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = base.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, getWidth(), getHeight());

        // DRAW STUFF
        Character.draw(g2d);

        // FINISH UP
        g.drawImage(base, 0, 0, null);
        g2d.dispose();
        g.dispose();
    }
}

The display class is contained in a JFrame:

public class Window extends JFrame {
    private Display display = new Display();

    public Window(String title, int width, int height){
        super(title);
        add(display);
        setSize(width, height);
        setIgnoreRepaint(false);
        setLocationRelativeTo(null);
        setResizable(false);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public Display getDisplay() {
        return display;
    }
}

enter image description here

This works fine, but I want to fill the part outside of the circle (and only that part) with a color.

I've tried using an AlphaComposite but I cant figure out how to use it to do this. I could just make a bigger circle and decrease the dist1 value but that takes too long to draw (around 10ms on my machine as opposed to the 2ms of the circle in the image). I'm trying to put this into a game.

How would I go about this? Thanks in advance and sorry if this has an obvious solution but I just can't put my finger on it.

If you need more information just ask.

1 Answers

Painting with non-opaque colors causes background to show, so you have to set the background, so you have to set the appropriate background.
Have a look at this demo :

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

public class APanel extends JPanel{

    APanel(){

        setPreferredSize(new Dimension(600,600));
        setBackground(Color.YELLOW);
        setBorder(new TitledBorder(new LineBorder(new Color(169, 169, 169)),
                "Gradient Circle", TitledBorder.LEADING, TitledBorder.BELOW_TOP, null, null));
    }

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

    public static void draw(Graphics2D g2d){

        g2d.setColor(Color.RED);
        g2d.fillRect(100,100, 400, 400);
        drawVisibilityCircle(g2d);
    }

    private static void drawVisibilityCircle(Graphics2D g2d){
        Point center = new Point(300, 300);
        float radius = 200;
        float[] dist = { 0f, 1f};
        Color[] colors = { new Color(0, 0, 0, 0), new Color(0, 0, 0, 255)};
        //workaround to prevent background color from showing
        drawBackGroundCircle(g2d, radius, Color.WHITE, center);
        drawGradientCircle(g2d, radius, dist, colors, center);
    }

    private static void drawBackGroundCircle(Graphics2D g2d, float radius, Color color, Point2D center){

        g2d.setColor(color);
        radius -= 1;//make radius a bit smaller to prevent fuzzy edge
        g2d.fill(new Ellipse2D.Double(center.getX() - radius, center.getY()
                                                    - radius, radius * 2, radius * 2));
    }

    private static void drawGradientCircle(Graphics2D g2d, float radius, float[] dist, Color[] colors, Point2D center){
        RadialGradientPaint rgp = new RadialGradientPaint(center, radius, dist, colors);
        g2d.setPaint(rgp);
        g2d.fill(new Ellipse2D.Double(center.getX() - radius, center.getY() - radius, radius * 2, radius * 2));
    }

    public static void main(String[] args){

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        JPanel panel = new APanel();
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}

enter image description here

Related