3

In Nimbus look and feel JButtons have a very tidy and accurate look, with rounded border and nice background.
I'd like to render a JPanel with the very same look (obviously it won't have pressed state etc).
What are my options?

Jonas
  • 121,568
  • 97
  • 310
  • 388
AgostinoX
  • 7,477
  • 20
  • 77
  • 137

1 Answers1

5

The easiest way to get "Button look" on a JPanel is probably by extending the JPanel and override paintComponent.

Here is the Nimbus JButton look:

enter image description here

And here is my implementation of a similar look on a JPanel (I added an empty border around for showing this example, and the corners are not translucent):

enter image description here

Here is my code (using gradients):

public class ColorDemo extends JPanel {

    private final int gradientSize = 18;
    private final Color lighterColor = new Color(250, 250, 250);
    private final Color darkerColor = new Color(225, 225, 230);
    private final Color edgeColor = new Color(140, 145, 145);
    private final Stroke edgeStroke = new BasicStroke(1);
    private final GradientPaint upperGradient = new GradientPaint(
            0, 0, lighterColor,
            0, gradientSize, darkerColor);


    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                            RenderingHints.VALUE_ANTIALIAS_ON);
        GradientPaint lowerGradient = new GradientPaint(
                0, getHeight()-gradientSize-1, darkerColor,
                0, getHeight(), lighterColor);
        g2.setPaint(upperGradient);
        g2.fillRect(0, 0, getWidth()-1 , gradientSize);
        g2.setPaint(darkerColor);
        g2.fillRect(0, gradientSize, getWidth()-1, getHeight()-gradientSize-1);
        g2.setPaint(lowerGradient);
        g2.fillRect(0, getHeight()-gradientSize, getWidth()-1, getHeight()-1);
        g2.setStroke(edgeStroke);
        g2.setPaint(edgeColor);
        g2.drawRoundRect(0, 0, getWidth()-1, getHeight()-1,
                               gradientSize/2, gradientSize/2);
    }
}

UPDATE

Here is an improved paintComponent method by AgostinoX that solved the corner issue in my code.

    @Override
    public void paintComponent(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALI‌​AS_ON);
        float gradientPerc = (float)gradientSize/getHeight();
        LinearGradientPaint lgp = new LinearGradientPaint(0,0,0,getHeight()-1,
           new float[] {0, gradientPerc, 1-gradientPerc, 1f},
           new Color[] {lighterColor, darkerColor, darkerColor, lighterColor});
        g2.setPaint(lgp);
        g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1,
            gradientSize, gradientSize);
        g2.setColor(edgeColor);
        g2.setStroke(edgeStroke);
        g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1,
            gradientSize, gradientSize);
    }

See also my answer to How to hide the arrow buttons in a JScrollBar on how you can customize the look and feel for Nimbus. And see the Nimbus defaults for colors and painters.

Community
  • 1
  • 1
Jonas
  • 121,568
  • 97
  • 310
  • 388
  • ok, i had a look to that question, it's very intresting; for the border, have you an idea where to get one similar to the one assigned to buttons? – AgostinoX Dec 13 '11 at 08:28
  • @AgostinoX: I think there is no easy way to get the same look. You have to override `paintComponent` in the `JPanel` and draw your own gradients. – Jonas Dec 13 '11 at 11:05
  • great job! The only thing i don't like is that the way you draw gradients, you fill the little corners out of the round border too. it is visible if you use a gradientSize>20. I've tried to improve this (good) solution, and come out with a multi-stop gradient, that simplifies the implementation as well. You find it in my next comment, it is a drop-in replacement for the paint method and replaces just the fillRect calls with a single call to fillRoundRect. Since the answer is yours, if you'd like to do this "improvement", then i will be happier to accept your answer :-). – AgostinoX Dec 19 '11 at 15:10
  • Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); float gradientPerc = (float)gradientSize/getHeight(); LinearGradientPaint lgp = new LinearGradientPaint(0,0,0,getHeight()-1, new float[] {0, gradientPerc, 1-gradientPerc, 1f}, new Color[] {lighterColor, darkerColor, darkerColor, lighterColor}); g2.setPaint(lgp); g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, gradientSize, gradientSize); g2.setColor(edgeColor); g2.setStroke(edgeStroke); g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, gradientSize,gradientSize); – AgostinoX Dec 19 '11 at 15:12
  • @AgostinoX: Great job! I updated my answer and added your code. – Jonas Dec 19 '11 at 15:26