0

I made my own RoundedBorder instead of using LineBorder with rounded corner because I wanted to set the arc size.

public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
    Graphics2D g2 = (Graphics2D) g;

    Shape roundRect = new RoundRectangle2D.Double(x + thickness / 2,
                                                  y + thickness / 2,
                                                  width - thickness,
                                                  height - thickness,
                                                  arcSize,
                                                  arcSize);
    Area area = new Area(roundRect);

    g2.setColor(color);
    g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
    g2.setStroke(new BasicStroke(thickness));

    g2.draw(area);
}

enter image description here



I used some code from border-with-rounded-corners-transparency to use the parent background color outside of the rounded borders. Though it does not work properly with TitledBorder taking a RoundedBorder as it does with only a RoundedBorder. Added the following code to my paintBorder.

    Component parent = c.getParent();
    if (parent != null) {
        Color bg = parent.getBackground();
        Rectangle rect = new Rectangle(x, y, width, height);
        Area borderRegion = new Area(rect);
        borderRegion.subtract(area);
        g2.setClip(borderRegion);
        g2.setColor(bg);
        g2.fillRect(x, y, width, height);
        g2.setClip(null);
    }


Any idea how to fix this to work properly? enter image description here



Edit: A new implementation of paintBorder is getting me a little closer:

    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
    Graphics2D g2 = (Graphics2D) g;

    Shape roundRect = new RoundRectangle2D.Double(x + thickness / 2,
                                                  y + thickness / 2,
                                                  width - thickness,
                                                  height - thickness,
                                                  arcSize,
                                                  arcSize);
    Area area = new Area(roundRect);

    final Rectangle componentRect = c.getBounds();
    final int componentWidth = (int) componentRect.getWidth();
    final int componentHeight = (int) componentRect.getWidth();

    // Paint the BG color of the parent in the entire rectangle of the component. 
    // Then repaint the area inside the border.
    Component parent = c.getParent();
    if (parent != null) {
        g2.setColor(parent.getBackground());
        g2.fillRect(0, 0, componentWidth, componentHeight);

        g2.setColor(c.getBackground());
        g2.fillRoundRect(x + thickness / 2,
                         y + thickness / 2,
                         width - thickness,
                         height - thickness,
                         arcSize,
                         arcSize);
    }

    g2.setColor(color);
    g2.setRenderingHints(hints);
    g2.setStroke(stroke);
    g2.draw(area);
}

enter image description here

Test Code Solution 1:

package com.test.gui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.AbstractBorder;
import javax.swing.border.TitledBorder;

public class TestBorderApp {

private JFrame frame;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                TestBorderApp window = new TestBorderApp();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public TestBorderApp() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel mainpanel = new JPanel();

    JPanel panel1 = new JPanel();
    panel1.setBackground(Color.RED);
    RoundedBorder roundBorder1 = new RoundedBorder(Color.BLACK, 5, 60);
    TitledBorder titleBorder1 = BorderFactory.createTitledBorder(roundBorder1, 
                        "Title", 
                        TitledBorder.CENTER, 
                        TitledBorder.ABOVE_TOP,
                        Font.decode(Font.SANS_SERIF), 
                        Color.BLACK);
    panel1.setBorder(titleBorder1);
    JLabel label1 = new JLabel("Text Text Text");
    panel1.add(label1);
    mainpanel.add(panel1);

    JPanel panel2 = new JPanel();
    panel2.setBackground(Color.RED);
    RoundedBorder roundBorder2 = new RoundedBorder(Color.BLACK, 5, 60);
    TitledBorder titleBorder2 = BorderFactory.createTitledBorder(roundBorder2, 
                        "Title", 
                        TitledBorder.CENTER, 
                        TitledBorder.TOP,
                        Font.decode(Font.SANS_SERIF), 
                        Color.BLACK);
    panel2.setBorder(titleBorder2);
    JLabel label2 = new JLabel("Text Text Text");
    panel2.add(label2);
    mainpanel.add(panel2);

    JPanel panel3 = new JPanel();
    panel3.setBackground(Color.RED);
    RoundedBorder roundBorder3 = new RoundedBorder(Color.BLACK, 5, 60);
    TitledBorder titleBorder3 = BorderFactory.createTitledBorder(
                        roundBorder3, 
                        "Title", 
                        TitledBorder.CENTER, 
                        TitledBorder.BELOW_TOP, 
                        Font.decode(Font.SANS_SERIF), 
                        Color.BLACK);
    panel3.setBorder(titleBorder3);
    JLabel label3 = new JLabel("Text Text Text");
    panel3.add(label3);
    mainpanel.add(panel3);

    frame.setContentPane(mainpanel);
}

public class RoundedBorder extends AbstractBorder {

    private static final long serialVersionUID = -6244878594068693694L;

    private Color color;

    private int thickness = 4;

    private int arcSize = 8;

    private BasicStroke stroke;

    private RenderingHints hints;

    /**
     * Constructor for round border
     *
     * @param color
     *            The color
     * @param thickness
     *            The thickness
     * @param arcSize
     *            the arc size
     */
    public RoundedBorder(Color color, int thickness, int arcSize) {
        this.thickness = thickness;
        this.arcSize = arcSize;
        this.color = color;
        this.stroke = new BasicStroke(thickness);
        this.hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }

    /**
     * Set the current color of the border
     *
     * @param color
     *            The color
     */
    public void setColor(Color color) {
        this.color = color;
    }

    /**
     * Get the current color of the border
     *
     * @return
     */
    public Color getColor() {
        return color;
    }

    public void setArcSize(int arcSize) {
        this.arcSize = arcSize;
    }

    public int getArcSize() {
        return arcSize;
    }

    /* (non-Javadoc)
     * @see javax.swing.border.AbstractBorder#getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    @Override
    public Insets getBorderInsets(Component c, Insets i) {
        i.set(thickness, thickness, thickness, thickness);
        return i;
    }

    /* (non-Javadoc)
     * @see javax.swing.border.AbstractBorder#paintBorder(java.awt.Component, java.awt.Graphics, int, int, int, int)
     */
    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        Graphics2D g2 = (Graphics2D) g;

        Shape roundRect = new RoundRectangle2D.Double(x + thickness / 2,
                                                      y + thickness / 2,
                                                      width - thickness,
                                                      height - thickness,
                                                      arcSize,
                                                      arcSize);
        Area area = new Area(roundRect);

        // Paint the BG color of the parent, everywhere outside the clip of the text bubble.
        Component parent = c.getParent();
        if (parent != null) {
            Color bg = parent.getBackground();
            Rectangle rect = new Rectangle(x, y, width, height);
            Area borderRegion = new Area(rect);
            borderRegion.subtract(area);
            g2.setClip(borderRegion);
            g2.setColor(bg);
            g2.fillRect(0, 0, width, height);
            g2.setClip(null);
        }

        g2.setColor(color);
        g2.setRenderingHints(hints);
        g2.setStroke(stroke);

        g2.draw(area);
    }

}
}

Test Code solution 2:

package com.test.gui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.AbstractBorder;
import javax.swing.border.TitledBorder;

public class TestBorderApp {

private JFrame frame;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                TestBorderApp window = new TestBorderApp();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public TestBorderApp() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel mainpanel = new JPanel();

    JPanel panel1 = new JPanel();
    panel1.setBackground(Color.RED);
    RoundedBorder roundBorder1 = new RoundedBorder(Color.BLACK, 5, 60);
    TitledBorder titleBorder1 = BorderFactory.createTitledBorder(roundBorder1, 
                        "Title", 
                        TitledBorder.CENTER, 
                        TitledBorder.ABOVE_TOP,
                        Font.decode(Font.SANS_SERIF), 
                        Color.BLACK);
    panel1.setBorder(titleBorder1);
    JLabel label1 = new JLabel("Text Text Text");
    panel1.add(label1);
    mainpanel.add(panel1);

    JPanel panel2 = new JPanel();
    panel2.setBackground(Color.RED);
    RoundedBorder roundBorder2 = new RoundedBorder(Color.BLACK, 5, 60);
    TitledBorder titleBorder2 = BorderFactory.createTitledBorder(roundBorder2, 
                        "Title", 
                        TitledBorder.CENTER, 
                        TitledBorder.TOP,
                        Font.decode(Font.SANS_SERIF), 
                        Color.BLACK);
    panel2.setBorder(titleBorder2);
    JLabel label2 = new JLabel("Text Text Text");
    panel2.add(label2);
    mainpanel.add(panel2);

    JPanel panel3 = new JPanel();
    panel3.setBackground(Color.RED);
    RoundedBorder roundBorder3 = new RoundedBorder(Color.BLACK, 5, 60);
    TitledBorder titleBorder3 = BorderFactory.createTitledBorder(
                        roundBorder3, 
                        "Title", 
                        TitledBorder.CENTER, 
                        TitledBorder.BELOW_TOP, 
                        Font.decode(Font.SANS_SERIF), 
                        Color.BLACK);
    panel3.setBorder(titleBorder3);
    JLabel label3 = new JLabel("Text Text Text");
    panel3.add(label3);
    mainpanel.add(panel3);

    frame.setContentPane(mainpanel);
}

public class RoundedBorder extends AbstractBorder {

    private static final long serialVersionUID = -6244878594068693694L;

    private Color color;

    private int thickness = 4;

    private int arcSize = 8;

    private BasicStroke stroke;

    private RenderingHints hints;

    /**
     * Constructor for round border
     *
     * @param color
     *            The color
     * @param thickness
     *            The thickness
     * @param arcSize
     *            the arc size
     */
    public RoundedBorder(Color color, int thickness, int arcSize) {
        this.thickness = thickness;
        this.arcSize = arcSize;
        this.color = color;
        this.stroke = new BasicStroke(thickness);
        this.hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }

    /**
     * Set the current color of the border
     *
     * @param color
     *            The color
     */
    public void setColor(Color color) {
        this.color = color;
    }

    /**
     * Get the current color of the border
     *
     * @return
     */
    public Color getColor() {
        return color;
    }

    public void setArcSize(int arcSize) {
        this.arcSize = arcSize;
    }

    public int getArcSize() {
        return arcSize;
    }

    /* (non-Javadoc)
     * @see javax.swing.border.AbstractBorder#getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    @Override
    public Insets getBorderInsets(Component c, Insets i) {
        i.set(thickness, thickness, thickness, thickness);
        return i;
    }

    /* (non-Javadoc)
     * @see javax.swing.border.AbstractBorder#paintBorder(java.awt.Component, java.awt.Graphics, int, int, int, int)
     */
    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        Graphics2D g2 = (Graphics2D) g;

        Shape roundRect = new RoundRectangle2D.Double(x + thickness / 2,
                                                      y + thickness / 2,
                                                      width - thickness,
                                                      height - thickness,
                                                      arcSize,
                                                      arcSize);
        Area area = new Area(roundRect);

        final Rectangle componentRect = c.getBounds();
        final int componentWidth = (int) componentRect.getWidth();
        final int componentHeight = (int) componentRect.getWidth();

        // Paint the BG color of the parent in the entire rectangle of the component.
        // Then repaint the area inside the border.
        Component parent = c.getParent();
        if (parent != null) {
            g2.setColor(parent.getBackground());
            g2.fillRect(0, 0, componentWidth, componentHeight);

            g2.setColor(c.getBackground());
            g2.fillRoundRect(x + thickness / 2,
                             y + thickness / 2,
                             width - thickness,
                             height - thickness,
                             arcSize,
                             arcSize);
        }

        g2.setColor(color);
        g2.setRenderingHints(hints);
        g2.setStroke(stroke);
        g2.draw(area);
    }

}}
Community
  • 1
  • 1
DJViking
  • 832
  • 1
  • 12
  • 29
  • 3
    For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example). – Andrew Thompson Dec 11 '14 at 12:01
  • Added the complete RoundedBorder class – DJViking Dec 11 '14 at 13:16
  • But it's still not a runnable example. The question you linked showed examples of what I'm talking about. 'Ready to run' code. – Andrew Thompson Dec 11 '14 at 13:53
  • I think the problem lies with TitledBorder. Since it is expanding the area and the RoundedBorder does not know about this. – DJViking Dec 11 '14 at 18:04
  • An MCVE should be ***one*** source file (that might contain more than one class). *Again* see how it is done in the linked question. It ain't rocket science.. – Andrew Thompson Dec 11 '14 at 23:38
  • Added one source file called TestBorderApp containing a runnable example for two different solutions. – DJViking Dec 12 '14 at 13:23

0 Answers0