我想要修改JButton
的渐变颜色,我找到了这篇文章:http://java2everyone.blogspot.com/2009/01/set-jbutton-gradient-color.html,但我只想为一个按钮更改渐变效果,并非所有的按钮。
我想要修改JButton
的渐变颜色,我找到了这篇文章:http://java2everyone.blogspot.com/2009/01/set-jbutton-gradient-color.html,但我只想为一个按钮更改渐变效果,并非所有的按钮。
您可以重写JButton
实例的paintComponent方法,并使用以下实现Paint接口的类之一来绘制其Graphics对象:
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();
}
}
}
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);
}
}
在 Metal LAF 中有一个硬编码异常。如果 background
属性是 UIResource
的子类,则会被忽略* ,并使用 UI 属性 Button.gradient
中的(也是硬编码的)渐变来绘制按钮。否则,如果 background
不是 UIResource
, 则直接按照该背景进行绘制。
* 除非按钮被禁用,在这种情况下没有渐变,并且使用 UIResource
中的颜色作为背景。
根据 MetalButtonUI
的逻辑,我发现它使用的渐变来自 UI 属性 Button.gradient
,其中包含 ArrayList
:
0 = {Float} 0.3
1 = {Float} 0.0
2 = {ColorUIResource} "[221,232,243]"
3 = {ColorUIResource} "[255,255,255]"
4 = {ColorUIResource} "[184,207,229]"
按照这个逻辑,我最终到达了MetalUtils.GradientPainter.drawVerticalGradient()
。这个实现将上面的数据解释为*:
*假设第二个浮点数为0.0,否则会绘制更多的渐变。
由于这是一个多阶段渐变,无法使用简单的GradientPaint
来完成,但可以使用LinearGradientPaint
来完成。然而,background
属性只接受Color
。它甚至无法被欺骗/黑客攻击,因为实际值最终被赋给Graphics.setColor()
而不是Graphics2D.setPaint()
(即使Metal基于Swing而不是AWT)死路一条。唯一的解决方案似乎是完全子类化JButton。