3

I have Line2D and Arc2D objects laid out on my JPanel by Graphics2D drawing. You can have a look a part of it on this question " How to make pixel perfect Line2D in - Graphics2D ". Now what I want to achieve is, I want to create two parallel lines and arcs for all Line2D and Arc2D objects. Visually,

Normal Line2D and Arc2D drawn currently,

enter image description here

Want to decorate it like this,

enter image description here

My Thoughts so far,

I might be able to achieve this by creating two different line and give an offset +gap and -gap from my normal line position. However This will make lots of objects which I don't want to.

Now, is it possible to make my normal line thicker like this,

enter image description here

and give them a border and delete middle bit from it?

Is it possible to achieve this? if yes, May I please have some direction.

Thank you for any kind of help.

Community
  • 1
  • 1
TeaCupApp
  • 11,316
  • 18
  • 70
  • 150
  • 1
    *"This will make lots of objects"* A 'second line' (or 100 of them, for a hundred primary lines) is not much to hold in memory. – Andrew Thompson Sep 08 '11 at 04:51

2 Answers2

3

Use a BasicStroke and draw it twice, thicker and thinner.

One line drawn twice

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;

import javax.imageio.ImageIO;
import java.io.File;

class PaintThick {

    public static void main(String[] args) throws Exception {
        int size = 150;
        final BufferedImage bi = new BufferedImage(
            size,size,BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();

        double pad = 20;
        Line2D.Double line1 = new Line2D.Double(
            pad,pad,(double)(size-pad),(double)(size-pad));
        int cap = BasicStroke.CAP_BUTT;
        int join = BasicStroke.JOIN_MITER;
        BasicStroke thick = new BasicStroke(15,cap,join);
        BasicStroke thinner = new BasicStroke(13,cap,join);

        g.setColor(Color.WHITE);
        g.fillRect(0,0,size,size);

        g.setColor(Color.BLACK);
        g.setStroke(thick);
        g.draw(line1);

        g.setColor(Color.WHITE);
        g.setStroke(thinner);
        g.draw(line1);

        ImageIO.write(bi,"png",new File("img.png"));
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JOptionPane.showMessageDialog(
                    null, new JLabel(new ImageIcon(bi)));
            }
        });
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
3

You can implement the Stroke interface to create a CompositeStroke, as shown here.

enter image description here

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;

/**
 * @see http://www.jhlabs.com/java/java2d/strokes/
 * @see http://stackoverflow.com/questions/7342979
 */
class StrokeTest {

    private static final int SIZE = 200;
    private static final double PAD = 20d;

    private static class CompositeStroke implements Stroke {

        private Stroke stroke1, stroke2;

        public CompositeStroke(Stroke stroke1, Stroke stroke2) {
            this.stroke1 = stroke1;
            this.stroke2 = stroke2;
        }

        @Override
        public Shape createStrokedShape(Shape shape) {
            return stroke2.createStrokedShape(
                stroke1.createStrokedShape(shape));
        }
    }

    public static void main(String[] args) throws Exception {
        final BufferedImage bi = new BufferedImage(
            SIZE, SIZE, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        Arc2D.Double shape = new Arc2D.Double(PAD, 2 * PAD,
            (SIZE - 2 * PAD), (SIZE - 2 * PAD), 0, 180d, Arc2D.OPEN);
        g.setColor(Color.white);
        g.fillRect(0, 0, SIZE, SIZE);
        BasicStroke s1 = new BasicStroke(16f);
        BasicStroke s2 = new BasicStroke(1f);
        g.setStroke(new CompositeStroke(s1, s2));
        g.setColor(Color.black);
        g.draw(shape);

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new JLabel(new ImageIcon(bi)));
                f.pack();
                f.setVisible(true);
            }
        });
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    I up-voted that before the code & screen-shot! Can I have another turn at up-voting? Nice call on the anti-aliasing. – Andrew Thompson Sep 08 '11 at 06:06
  • Nice thanks, I wish StackOverFlow let user choose how much reputation they want to award :) like there are two answer in front of me and they both are good. – TeaCupApp Sep 08 '11 at 07:07