4

I want to make JTextArea has a rounded corners, and i did this code :

public BPosTxtArea() {
    super();
    setOpaque(false);
}

@Override
protected void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getBackground());
    g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
    super.paintComponent(g);
}

@Override
protected void paintBorder(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(new Color(102, 102, 102));
    g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
}

but it still has a square border outside like picture bellow :

enter image description here

Can anyone help me?

Hanif NR
  • 113
  • 7
  • 3
    Did you add the text area to a JScrollPane? Maybe you are seeing the Border of the scroll pane. Post a proper [SSCCE](http://sscce.org/) that demonstrates the problem. – camickr Dec 22 '15 at 05:26
  • No i just want it has rounded corners – Hanif NR Dec 22 '15 at 05:34
  • *"i just want it has rounded corners"* Just post a [mcve] or SSCCE. Voting to close. – Andrew Thompson Dec 22 '15 at 05:55
  • Duplicate of [Border with rounded corners & transparency](http://stackoverflow.com/q/15025092/418556). (Someone else will need to close it, given I added, then retracted a prior close vote, I cannot close it.) – Andrew Thompson Dec 22 '15 at 05:59

2 Answers2

8

Start by having a look at How to Use Borders

This is a very simple example:

public class RoundBorder implements Border {

    private int radius;

    public RoundBorder(int radius) {
        this.radius = radius;
    }

    public int getRadius() {
        return radius;
    }

    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
        g2d.dispose();
    }

    @Override
    public Insets getBorderInsets(Component c) {
        int value = getRadius() / 2;
        return new Insets(value, value, value, value);
    }

    @Override
    public boolean isBorderOpaque() {
        return false;
    }

}

Rounded Border

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;

public class Example {

    public static void main(String[] args) {
        new Example();
    }

    public Example() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            JTextArea ta = new JTextArea(10, 20);
            ta.setBorder(new RoundBorder(20));

            JScrollPane sp = new JScrollPane(new JTextArea(10, 20));
            sp.setBorder(new RoundBorder(20));

            add(ta, gbc);
            add(sp, gbc);
        }

    }

    public class RoundBorder implements Border {

        private int radius;

        public RoundBorder(int radius) {
            this.radius = radius;
        }

        public int getRadius() {
            return radius;
        }

        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
            g2d.dispose();
        }

        @Override
        public Insets getBorderInsets(Component c) {
            int value = getRadius() / 2;
            return new Insets(value, value, value, value);
        }

        @Override
        public boolean isBorderOpaque() {
            return false;
        }

    }

}

Problems, the border is painted "within" the component fill area, meaning that the corners will be the same color as the fill area. There's no way around it using Border.

The trick would be to create a second component, onto which you could paint the border (via the paintComponent, filling the area within the border the same color as the text area) and then add the component into that.

Updated

Based on you code example, you're not overriding getInsets, which is going to be very important, the other thing is, it appears that your JTextArea is within a JScrollPane...

Comparison

public class BPosTextArea extends JTextArea {

    private int radius;

    public BPosTextArea() {
        super(10, 20);
        setOpaque(false);
        setBorder(null);
        setRadius(20);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(getBackground());
        g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
        super.paintComponent(g);
    }

    @Override
    protected void paintBorder(Graphics g) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(new Color(102, 102, 102));
        g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
    }

    public void setRadius(int radius) {
        this.radius = radius;
        repaint();
    }

    public int getRadius() {
        return radius;
    }

    @Override
    public Insets getInsets() {
        int value = getRadius() / 2;
        return new Insets(value, value, value, value);
    }

}

A solution is to set the border to null for the JScrollPane

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I did `setBorder` to null and overriding method `getInsets` but there's no change. Is there any other way to remove `JScrollPane` ? – Hanif NR Dec 22 '15 at 07:13
  • 2
    You don't want to remove the `JScrollPane`, setting the `JScrollPane`'s `border` to `null` "should" remove it. You may also need to make the `JScrollPane`'s `JViewport` transparent as well as the `JScrollPane` itself – MadProgrammer Dec 22 '15 at 07:36
0

Your code is fine, the detail is that JTextArea is linked to a JScrollPane which is adding that border to your TextArea, I corrected it this way. You must check what scrollpane is linked to once identified in the constructor of your class you must add this.

 jScrollPane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));

and your textarea will look like this:

example

You can give more style to your scroll but that is already separate.

cyberbrain
  • 3,433
  • 1
  • 12
  • 22