4

I want to use a Bevel Border because it is sort of 3D but I don't know how to create a rounded corner BevelBorder.

SoftBevelBorder does not work because the rounded radius is too small. How to make the corners more round?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Bashir Beikzadeh
  • 761
  • 8
  • 15
  • 1
    Possible duplicate of [Internal padding for JTextArea with background Image](http://stackoverflow.com/questions/8462414/internal-padding-for-jtextarea-with-background-image) – trashgod Jul 04 '12 at 01:38

2 Answers2

3

Here there is an example of rounded border, where you can adjust the radius:

http://java-swing-tips.blogspot.co.at/2012/03/rounded-border-for-jtextfield.html

Not bevel, but you can see how to achieve the "bevelness" in the source code of SoftBevelBorder. If you manage to do it, I would be interested in the code :)

lbalazscs
  • 17,474
  • 7
  • 42
  • 50
3

In order to get the correct border shape you need to override the AbstractBorder.paintBorder(...) method. When you do that you can add code similar to this to the method.

super.paintBorder(c, g, x, y, width, height);

Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));

Shape clip = g2d.getClip();
Area rect = new Area(clip);
rect.subtract(new Area(new RoundRectangle2D.Double(x, y, width, height, radii, radii)));
g2d.setClip(rect);
g2d.setColor(c.getParent().getBackground());
g2d.fillRect(0, 0, width, height);
g2d.setClip(clip);
g2d.draw(rect);

Now there are two main ways you can draw a bevel effect around the border but depending on the complexity you want the bevel to be, depends on which way you use. For a simple bevel border that uses 2 colours, you can use something similar to this.

g2d.setColor(inner); //Inner Rectangle
g2d.draw(new RoundRectangle2D.Double(x + 1, y + 1, width - 2, height - 2, radii, radii));

g2d.setColor(outer); //Outer Rectangle
g2d.draw(new RoundRectangle2D.Double(x, y, width - 2, height - 2, radii, radii));

However, if you want to use a more complex bevel border that uses 4 different colours, you will need to look at the source code of javax.swing.border.BevelBorder. This will show you that you need a piece of code similar to this.

double offset = radii / 2;
//Outer
g2d.setColor(outerH);
g2d.draw(new Line2D.Double(0, offset, 0, height - 2 - offset)); //Left
g2d.draw(new Line2D.Double(1 + offset, 0, width - 2 - offset, 0)); //Top
g2d.draw(new Arc2D.Double(width - radii - 1, 0, radii, radii, 0, 90, Arc2D.OPEN)); //Top Right
g2d.draw(new Arc2D.Double(0, 0, radii, radii, 90, 90, Arc2D.OPEN)); //Top Left

//Inner
g2d.setColor(innerH);
g2d.draw(new Line2D.Double(1, 1 + offset, 1, height - 3 - offset)); //Left
g2d.draw(new Line2D.Double(2 + offset, 1, width - 3 - offset, 1)); //Top
g2d.draw(new Arc2D.Double(width - radii - 2, 1, radii, radii, 0, 90, Arc2D.OPEN)); //Top Right
g2d.draw(new Arc2D.Double(1, 1, radii, radii, 90, 90, Arc2D.OPEN)); //Top Left

//Outer
g2d.setColor(outer);
g2d.draw(new Line2D.Double(offset, height - 1, width - 1 - offset, height - 1)); //Bottom
g2d.draw(new Line2D.Double(width - 1, offset, width - 1, height - 2 - offset)); //Right
g2d.draw(new Arc2D.Double(width - radii - 1, height - radii - 1, radii, radii, 270, 90, Arc2D.OPEN)); //Bottom Right
g2d.draw(new Arc2D.Double(0, height - radii - 1, radii, radii, 180, 90, Arc2D.OPEN)); //Bottom Left

//Inner
g2d.setColor(inner);
g2d.draw(new Line2D.Double(1 + offset, height - 2, width - 2 - offset, height - 2)); //Bottom
g2d.draw(new Line2D.Double(width - 2, 1 + offset, width - 2, height - 3 - offset)); //Right
g2d.draw(new Arc2D.Double(width - radii - 2, height - radii - 2, radii, radii, 270, 90, Arc2D.OPEN)); //Bottom Right
g2d.draw(new Arc2D.Double(1, height - radii - 2, radii, radii, 180, 90, Arc2D.OPEN)); //Bottom Left

You may also use the following code if it is important for the color to stop half way around the corner.

double offset = radii / 2;
//Outer
g2d.setColor(outerH);
g2d.draw(new Line2D.Double(0, offset, 0, height - 2 - offset)); //Left
g2d.draw(new Line2D.Double(1 + offset, 0, width - 2 - offset, 0)); //Top
g2d.draw(new Arc2D.Double(width - radii - 1, 0, radii, radii, 45, 45, Arc2D.OPEN)); //Top Right P1
g2d.draw(new Arc2D.Double(0, 0, radii, radii, 90, 90, Arc2D.OPEN)); //Top Left
g2d.draw(new Arc2D.Double(0, height - radii - 1, radii, radii, 180, 45, Arc2D.OPEN)); //Bottom Left P1

//Inner
g2d.setColor(innerH);
g2d.draw(new Line2D.Double(1, 1 + offset, 1, height - 3 - offset)); //Left
g2d.draw(new Line2D.Double(2 + offset, 1, width - 3 - offset, 1)); //Top
g2d.draw(new Arc2D.Double(width - radii - 2, 1, radii, radii, 45, 45, Arc2D.OPEN)); //Top Right P1
g2d.draw(new Arc2D.Double(1, 1, radii, radii, 90, 90, Arc2D.OPEN)); //Top Left
g2d.draw(new Arc2D.Double(1, height - radii - 2, radii, radii, 180, 45, Arc2D.OPEN)); //Bottom Left P1

//Outer
g2d.setColor(outerS);
g2d.draw(new Line2D.Double(offset, height - 1, width - 1 - offset, height - 1)); //Bottom
g2d.draw(new Line2D.Double(width - 1, offset, width - 1, height - 2 - offset)); //Right
g2d.draw(new Arc2D.Double(width - radii - 1, 0, radii, radii, 0, 45, Arc2D.OPEN)); //Top Right P2
g2d.draw(new Arc2D.Double(width - radii - 1, height - radii - 1, radii, radii, 270, 90, Arc2D.OPEN)); //Bottom Right
g2d.draw(new Arc2D.Double(0, height - radii - 1, radii, radii, 225, 45, Arc2D.OPEN)); //Bottom Left P2

//Inner
g2d.setColor(innerS);
g2d.draw(new Line2D.Double(1 + offset, height - 2, width - 2 - offset, height - 2)); //Bottom
g2d.draw(new Line2D.Double(width - 2, 1 + offset, width - 2, height - 3 - offset)); //Right
g2d.draw(new Arc2D.Double(width - radii - 2, 1, radii, radii, 0, 45, Arc2D.OPEN)); //Top Right P2
g2d.draw(new Arc2D.Double(width - radii - 2, height - radii - 2, radii, radii, 270, 90, Arc2D.OPEN)); //Bottom Right
g2d.draw(new Arc2D.Double(1, height - radii - 2, radii, radii, 225, 45, Arc2D.OPEN)); //Bottom Left P2

When we put all this together you get a class that looks like this.

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.border.AbstractBorder;

@SuppressWarnings("serial")
public class RoundedBorder extends AbstractBorder {
    private int radii;
    private Insets insets;
    private Color innerS = new Color(166, 166, 166);
    private Color outerS = new Color(116, 116, 116);
    private Color innerH = Color.WHITE; 
    private Color outerH = Color.WHITE;
    private boolean tColor = false;

    public RoundedBorder(int radius) {
        radii = radius;
    }

    public RoundedBorder(int radius, Insets i) {
        radii = radius;
        insets = i;
    }

    public RoundedBorder(int radius, Insets i, Color out, Color in) {
        radii = radius;
        insets = i;
        innerS = in;
        outerS = out;
        tColor = true;
    }

    public RoundedBorder(int radius, Insets i, Color outH, Color inH, Color outS, Color inS) {
        radii = radius;
        insets = i;
        innerS = inS;
        outerS = outS;
        innerH = inH;
        outerH = outH;
    }

    @Override
    public Insets getBorderInsets(Component c) {
        if(insets != null) {
            return insets;
        }
        return new Insets(5, 5, 5, 5);
    }

    @Override
    public Insets getBorderInsets(Component c, Insets insets) {
        return getBorderInsets(c);
    }

    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        super.paintBorder(c, g, x, y, width, height);

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));

        Shape clip = g2d.getClip();
        Area rect = new Area(clip);
        rect.subtract(new Area(new RoundRectangle2D.Double(x, y, width, height, radii, radii)));
        g2d.setClip(rect);
        g2d.setColor(c.getParent().getBackground());
        g2d.fillRect(0, 0, width, height);
        g2d.setClip(clip);
        g2d.draw(rect);

        if(!tColor) {
            double offset = radii / 2;
            //Outer
            g2d.setColor(outerH);
            g2d.draw(new Line2D.Double(0, offset, 0, height - 2 - offset)); //Left
            g2d.draw(new Line2D.Double(1 + offset, 0, width - 2 - offset, 0)); //Top
            g2d.draw(new Arc2D.Double(width - radii - 1, 0, radii, radii, 45, 45, Arc2D.OPEN)); //Top Right P1
            g2d.draw(new Arc2D.Double(0, 0, radii, radii, 90, 90, Arc2D.OPEN)); //Top Left
            g2d.draw(new Arc2D.Double(0, height - radii - 1, radii, radii, 180, 45, Arc2D.OPEN)); //Bottom Left P1

            //Inner
            g2d.setColor(innerH);
            g2d.draw(new Line2D.Double(1, 1 + offset, 1, height - 3 - offset)); //Left
            g2d.draw(new Line2D.Double(2 + offset, 1, width - 3 - offset, 1)); //Top
            g2d.draw(new Arc2D.Double(width - radii - 2, 1, radii, radii, 45, 45, Arc2D.OPEN)); //Top Right P1
            g2d.draw(new Arc2D.Double(1, 1, radii, radii, 90, 90, Arc2D.OPEN)); //Top Left
            g2d.draw(new Arc2D.Double(1, height - radii - 2, radii, radii, 180, 45, Arc2D.OPEN)); //Bottom Left P1

            //Outer
            g2d.setColor(outerS);
            g2d.draw(new Line2D.Double(offset, height - 1, width - 1 - offset, height - 1)); //Bottom
            g2d.draw(new Line2D.Double(width - 1, offset, width - 1, height - 2 - offset)); //Right
            g2d.draw(new Arc2D.Double(width - radii - 1, 0, radii, radii, 0, 45, Arc2D.OPEN)); //Top Right P2
            g2d.draw(new Arc2D.Double(width - radii - 1, height - radii - 1, radii, radii, 270, 90, Arc2D.OPEN)); //Bottom Right
            g2d.draw(new Arc2D.Double(0, height - radii - 1, radii, radii, 225, 45, Arc2D.OPEN)); //Bottom Left P2

            //Inner
            g2d.setColor(innerS);
            g2d.draw(new Line2D.Double(1 + offset, height - 2, width - 2 - offset, height - 2)); //Bottom
            g2d.draw(new Line2D.Double(width - 2, 1 + offset, width - 2, height - 3 - offset)); //Right
            g2d.draw(new Arc2D.Double(width - radii - 2, 1, radii, radii, 0, 45, Arc2D.OPEN)); //Top Right P2
            g2d.draw(new Arc2D.Double(width - radii - 2, height - radii - 2, radii, radii, 270, 90, Arc2D.OPEN)); //Bottom Right
            g2d.draw(new Arc2D.Double(1, height - radii - 2, radii, radii, 225, 45, Arc2D.OPEN)); //Bottom Left P2
        } else {
            g2d.setColor(innerS); //Inner Rectangle
            g2d.draw(new RoundRectangle2D.Double(x + 1, y + 1, width - 2, height - 2, radii, radii));

            g2d.setColor(outerS); //Outer Rectangle
            g2d.draw(new RoundRectangle2D.Double(x, y, width - 2, height - 2, radii, radii));
        }
    }
}

Now you can implement this class on your component by just doing yourComponent.setBorder(new RoundedBorder(10)); or by using one of the other constructors for the RoundedBorder class.

Dan
  • 7,286
  • 6
  • 49
  • 114
  • 1
    I tried it, and it does look rounded, but not bevelled, at least not in a way that is similar to BevelBorder... – lbalazscs Dec 15 '16 at 17:05
  • @lbalazscs Thank you for your feedback. I should have tried it with the initial bevel border colours before posting. I have edited the code so that when you use `yourComponent.setBorder(new RoundedBorder(10));` it will look a lot more "bevelly" (pretty sure that's not a word :P) by default – Dan Dec 15 '16 at 18:05
  • @lbalazscs Would you say it looks better or should I change it somehow? – Dan Dec 15 '16 at 18:05
  • 1
    It's much better now, much more "bevelly" :) This should be the accepted answer, not mine. – lbalazscs Dec 15 '16 at 18:42
  • @lbalazscs I'm happy with it being yours as I got the idea from your answer. I just implemented it :) Again thanks for the feedback – Dan Dec 15 '16 at 18:44
  • Thank you, very well written and versatile class. – JFreeman Apr 16 '19 at 10:32