How to create a JButton extension with rounded corners?

13,437

Solution 1

I think you've got 2 choices here:

1.Implement drawing yourself in a paint method of your component

2.Create new ButtonUI for your look and feel. In this case i would suggest to use Synch LAF

In both cases drawing different states is your resposibility

Solution 2

The best implementation I have seen of rounded buttons in Swing are in the Substance look and feel:

https://substance.dev.java.net/

Not all themes have rounded buttons so you may need to change the defaults in the demo. The project is open source so it might be worth poking around in the code for some ideas.

Solution 3

I needed to make this as well, this is what I ended up with (Metal LAF only!)

@Override
    protected void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
        Shape firstClip = g.getClip();
        RoundRectangle2D rect = new RoundRectangle2D.Double();
        double arc = Math.ceil(getSize().getHeight()/3);
        rect.setRoundRect(0, 0, Math.ceil(getSize().getWidth()), Math.ceil(getSize().getHeight()), arc, arc);
        Area secondClip = new Area(getBounds());
        secondClip.subtract(new Area(rect));
        Area finalClip = new Area(firstClip);
        finalClip.subtract(secondClip);
        g2.setClip(finalClip);
        super.paintComponent(g2);
        Color[] gradients;
        if(getModel().isRollover())
        {
            gradients = new Color[] { new Color(184, 207, 229), new Color(122, 138, 153), new Color(184, 207, 229) };
        }
        else
        {
            gradients = new Color[] { new Color(122, 138, 153) };
        }
        for(int i = 0; i < gradients.length; i++)
        {
            arc -= 2;
            g2.setColor(gradients[i]);
            g2.drawRoundRect(i+1, i+1, (int)Math.ceil(getSize().getWidth()-2)-(i*2), (int)Math.ceil(getSize().getHeight()-2)-(i*2), (int)arc, (int)arc);
        }
    }

Which looks like this: http://i.stack.imgur.com/unZuc.png

Share:
13,437
Boris Pavlović
Author by

Boris Pavlović

Interested in developing programming, concurrent model design skills, design patterns, refactoring, testing... Computer languages: java, javaScript, sql, fsp, erlang...

Updated on June 05, 2022

Comments

  • Boris Pavlović
    Boris Pavlović about 2 years

    This is a continuation of the question "Java rounded Swing JButton". I have searched for an extension of javax.swing.JButton which will inherit all runtime behavior and just override drawing of the corners.

    Using the code given by noah.w on sun forums page the result looks like this:

    alt text

    I'd like to be able to have the same gradient in the background, on mouse over change etc. Does anybody know how to do that?

    Code which creates the Java Swing window from the picture is:

    public class XrButton extends JButton implements MouseListener {
    
        private static final long serialVersionUID = 9032198251140247116L;
    
        String text;
        boolean mouseIn = false;
    
        public XrButton(String s) {
            super(s);
            text = s;
            setBorderPainted(false);
            addMouseListener(this);
            setContentAreaFilled(false);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            if (getModel().isPressed()) {
                g.setColor(g.getColor());
                g2.fillRect(3, 3, getWidth() - 6, getHeight() - 6);
            }
            super.paintComponent(g);
    
            if (mouseIn)
                g2.setColor(Color.red);
            else
                g2.setColor(new Color(128, 0, 128));
    
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setStroke(new BasicStroke(1.2f));
            g2.draw(new RoundRectangle2D.Double(1, 1, (getWidth() - 3),
                    (getHeight() - 3), 12, 8));
            g2.setStroke(new BasicStroke(1.5f));
            g2.drawLine(4, getHeight() - 3, getWidth() - 4, getHeight() - 3);
    
            g2.dispose();
        }
    
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.getContentPane().setLayout(new FlowLayout());
    
            XrButton xrButton = new XrButton("XrButton");
            JButton jButton = new JButton("JButton");
    
            frame.getContentPane().add(xrButton);
    
            frame.getContentPane().add(jButton);
    
            frame.setSize(150, 150);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    
        public void mouseClicked(MouseEvent e) {
        }
    
        public void mouseEntered(MouseEvent e) {
            mouseIn = true;
        }
    
        public void mouseExited(MouseEvent e) {
            mouseIn = false;
        }
    
        public void mousePressed(MouseEvent e) {
        }
    
        public void mouseReleased(MouseEvent e) {
        }
    
  • John Gardner
    John Gardner about 15 years
    Agreed. StackOverflow isn't about doing ALL of your work for you. If you want to do gradients, i'm sure someone's asked "how do i draw a gradient in swing" (See GradientPaint), etc.