Change JButton gradient color, but only for one button, not all
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 onl开发者_C百科y one button, not all button
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:
- GradientPaint.
- LinearGradientPaint
- MultipleGradientPaint
- RadialGradientPaint
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();
}
}
}
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);
}
}
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.
精彩评论