4

Is there a method to to add dashed border only from one side to a Java Swing component like JPanel or JLabel?

The question is not duplicate of another question because that question refers to a line border for one side. But I need dashed border.

Community
  • 1
  • 1
mortalis
  • 2,060
  • 24
  • 34
  • 1
    [This](http://stackoverflow.com/a/2174361/3377857) one should help! – Klemens Morbe Apr 22 '15 at 13:39
  • possible duplicate of [Is it possible to have a java swing border only on the top side?](http://stackoverflow.com/questions/2174319/is-it-possible-to-have-a-java-swing-border-only-on-the-top-side) – Kevin Workman Apr 22 '15 at 13:43
  • Have you done any research at all for this? Look through the docs of the BorderFacotry class and see if you get anything. http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html – CaffeineToCode Apr 22 '15 at 13:44
  • Thanks. Of course I looked for some sources and APIs. The `BorderFactory` gives the `createDashedBorder()` method which draws borders from each side. – mortalis Apr 22 '15 at 14:15

2 Answers2

5

The question is not duplicate of another question because that question refers to a line border for one side

Yes, it is a duplicate, because the API shows you how to use an MatteBorder with an Icon on a single side. So all you need to do is create a "Dashed Line Icon". See the example posted in my code below.

Or a second option, not listed in the posting, is to use a CompoundBorder to create the effect that you want:

Border empty = BorderFactory.createEmptyBorder(0, -1, -1, -1);
Border dashed = BorderFactory.createDashedBorder(null, 5, 5);
Border compound = new CompoundBorder(empty, dashed);

By setting the EmptyBorder dimension to -1 you set the combined dimension to 0, so the DashedBorder only gets painted on one side.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class DashedBorder extends JPanel
{
    public DashedBorder()
    {
        //  Use an Icon in the MatteBorder

        JLabel label1 = new JLabel("Label Using a Matte Border");
        add(label1);

        Icon icon = new DashedLineIcon(Color.BLACK, 5, 1, 5, 0);
        Border matte = BorderFactory.createMatteBorder(1, 0, 0, 0, icon);
        label1.setBorder( matte );
        System.out.println(matte.getBorderInsets(label1));

        add(Box.createHorizontalStrut(100));
        //  Create a CompoundBorder using the DashedBorder

        JLabel label2 = new JLabel("Label Using a Dashed Border");
        add(label2);

        Border dashed = BorderFactory.createDashedBorder(null, 5, 5);
        Border empty = BorderFactory.createEmptyBorder(1, -1, -1, -1);
        Border compound = new CompoundBorder(empty, dashed);
        label2.setBorder( compound );
        System.out.println(compound.getBorderInsets(label2));

    }

    static public class DashedLineIcon implements Icon
    {
        private Color color;
        private int dashWidth;
        private int dashHeight;
        private int emptyWidth;
        private int emptyHeight;

        public DashedLineIcon(Color color, int dashWidth, int dashHeight, int emptyWidth, int emptyHeight )
        {
            this.color = color;
            this.dashWidth = dashWidth;
            this.dashHeight = dashHeight;
            this.emptyWidth = emptyWidth;
            this.emptyHeight = emptyHeight;
        }

        public int getIconWidth()
        {
            return dashWidth + emptyWidth;
        }

        public int getIconHeight()
        {
            return dashHeight + emptyHeight;
        }

        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            g.setColor(color);
            g.fillRect(x, y, dashWidth, dashHeight);
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Dashed Border");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new DashedBorder());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thank you. Thought that `icon` is only for images. But the negative `EmptyBorder` widths is better. – mortalis Apr 22 '15 at 19:29
-1

Also I came to this solution, though it's a little more complex:

private void drawBorder(Graphics g){
  int x = this.getWidth();
  float dash[] = {1.0f};
  Graphics2D g2;
  BasicStroke stroke;

  g2 = (Graphics2D)g;
  stroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, dash, 0.0f);
  g2.setStroke(stroke);
  g2.setColor((Color) new Color(120, 120, 120));

  g2.draw(new Line2D.Double(0, 0, x, 0));
}

panel = new JPanel(){
  @Override
  public void paintComponent(Graphics g){
    drawBorder(g);
  }
};

Here I drew the top line with Graphics2D methods and using BasicStroke class to create dashes which are actually dots because the density array dash tells it to have space of 1 between dashes as the dashes lengths.

mortalis
  • 2,060
  • 24
  • 34
  • 1-, No that is not the way to do that. Don't hardcode the painting into your component. Create a reusable Border. Just create your own custom Border and move that painting code to the `paintBorder(...)` method of your custom Border. Or create a custom Icon that does exactly what your want and use the MatteBorder. I already gave you an example of how to do this. – camickr Apr 22 '15 at 19:44
  • Swing already has a Border API and you have been give two simple ways to implement the Border. So overriding the paintComponent() method to paint a border is reinventing the wheel. Also, the code is not reusable. The Border API provides you an easy way to make any custom Border reusable. – camickr Apr 22 '15 at 20:20
  • Sorry, but what means it's not reusable? I cannot apply this border drawing methods to other components? Or it lacks parameters to become more general? – mortalis Apr 22 '15 at 20:23
  • Correct, you can't add the Border to a label or a text field or a button unless you do custom painting for every component. The whole point of using the Border interface is so you don't have to keep doing custom painting and by extending components. – camickr Apr 22 '15 at 20:38
  • OK, understood. So for me implementing `Border` is a good choice. Thanks for your teaching and for your time. I appreciate it. – mortalis Apr 22 '15 at 20:53