I want to change JButton
gradient color,
i found this, http://java2everyone.blogspot.com/2009/01/set-jbutton-gradient-color.html, but i want to change gradient for only one button, not all button
3 Answers
You can override the paintComponent method of the JButton
instance and paint its Graphics object with one of the following classes that implement the Paint interface:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public final class JGradientButtonDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
final JFrame frame = new JFrame("Gradient JButton Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout());
frame.add(JGradientButton.newInstance());
frame.setSize(new Dimension(300, 150)); // used for demonstration
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class JGradientButton extends JButton {
private JGradientButton() {
super("Gradient Button");
setContentAreaFilled(false);
setFocusPainted(false); // used for demonstration
}
@Override
protected void paintComponent(Graphics g) {
final Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(new GradientPaint(
new Point(0, 0),
Color.WHITE,
new Point(0, getHeight()),
Color.PINK.darker()));
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
super.paintComponent(g);
}
public static JGradientButton newInstance() {
return new JGradientButton();
}
}
}

- 43,520
- 33
- 120
- 170
-
1since should be L&F sensitive, but vey nice +1 – mKorbel Aug 19 '11 at 06:20
-
1best solution i've found on SO – Ray Hulha Nov 13 '11 at 21:01
A little improvement over mre answer:
private static final class JGradientButton extends JButton{
private JGradientButton(String text){
super(text);
setContentAreaFilled(false);
}
@Override
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g.create();
g2.setPaint(new GradientPaint(
new Point(0, 0),
getBackground(),
new Point(0, getHeight()/3),
Color.WHITE));
g2.fillRect(0, 0, getWidth(), getHeight()/3);
g2.setPaint(new GradientPaint(
new Point(0, getHeight()/3),
Color.WHITE,
new Point(0, getHeight()),
getBackground()));
g2.fillRect(0, getHeight()/3, getWidth(), getHeight());
g2.dispose();
super.paintComponent(g);
}
}

- 7,178
- 7
- 41
- 55
-
How would one implement this to a button that is already part of a GUI? Would I need to change the action listeners at all if I added this to the buttons? Is that possible? Or, better question; is it a reasonable question to ask in the first place? – Ethan Moore Apr 30 '16 at 07:40
-
If a GUI has already a button, there must be some code that creates that button (JButton b = new JButton("whatever") ). To replace the default button, you need to create a JGradientButton instead (JButton b = new JGradientButton("whatever") ) and set the background color to what you like (b.setBackground(..somecolor...)) . The remaining code in the GUI that handle the button should be left unchanged – luca Apr 30 '16 at 20:59
-
1For eample in NetBeans' Gui Builder, select the button, go to the Properties tab 'Code', change 'Custom Creation Code'. – Mark Jeronimus Nov 22 '18 at 11:16
TL;DR: it's not possible directly, but can be done with a workaround like in Luca's answer, however his/her answer uses the incorrect gradient steps. The correct ones are listed below.
The way it works
In the Metal LAF there is a hardcoded exception. If the background
property is a subclass of UIResource
, it's ignored* and the button is instead painted with the (also hardcoded) gradient from the UI property Button.gradient
. Otherwise, if background
is not a UIResource
, that background is painted as-is.
*unless the button is disabled, in which case there is no gradient and the color inside the UIResource
is used for the background.
The gradient
Following the logic of MetalButtonUI
, I found out the used gradient it uses comes from the UI property Button.gradient
, which contains the ArrayList
:
0 = {Float} 0.3
1 = {Float} 0.0
2 = {ColorUIResource} "[221,232,243]"
3 = {ColorUIResource} "[255,255,255]"
4 = {ColorUIResource} "[184,207,229]"
Following the logic even further, I ended up in MetalUtils.GradientPainter.drawVerticalGradient()
. This implementation interprets the above data as*:
- Gradient from 0% to 30%: color1 to color2
- Gradient from 30% to 60%: color2 to color1
- Gradient from 60% to 100%: color1 to color3
*assuming the second float is 0.0, otherwise more gradients are drawn.
Since this is a multi-stage gradient, it can't be done with a simple GradientPaint
but can be done with a LinearGradientPaint
. However the background
property only accepts Color
. It cannot even be spoofed/hacked because the actual value is eventually given to Graphics.setColor()
and not Graphics2D.setPaint()
(even though Metal is Swing-based and not AWT) Dead End. The only solution seems to subclass JButton altogether.

- 9,278
- 3
- 37
- 50