更改 JButton 渐变颜色,但仅针对一个按钮,而不是全部

发布于 2024-11-30 11:39:29 字数 249 浏览 1 评论 0 原文

我想更改 JButton 渐变颜色, 我发现了这个, http://java2everyone.blogspot.com/2009 /01/set-jbutton-gradient-color.html,但我只想更改一个按钮的渐变,而不是所有按钮

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心是晴朗的。 2024-12-07 11:39:29

您可以覆盖 JButton 实例的 >paintComponent 方法并绘制其 Graphics 对象,具有以下实现 Paint 接口:


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();
        }
    }
}

在此处输入图像描述

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();
        }
    }
}

enter image description here

药祭#氼 2024-12-07 11:39:29

比 mre 答案有一点改进:

在此处输入图像描述

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);
    }
}

A little improvement over mre answer:

enter image description here

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);
    }
}
浅听莫相离 2024-12-07 11:39:29

TL;DR:这不可能直接实现,但可以通过像 Luca 的答案中那样的解决方法来完成,但是他/她的答案使用了不正确的梯度步骤。下面列出了正确的。

工作方式

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% 到 30% 的渐变:color1 到 color2
  • 从 30% 到 60% 的渐变:color2 到 color1
  • 从 60% 到 100% 的渐变:color1 到 color3

*假设第二个浮点数为 0.0,否则会绘制更多渐变。

由于这是多阶段渐变,因此无法使用简单的 GradientPaint 来完成,但可以使用 LinearGradientPaint 来完成。但是,background 属性仅接受Color。它甚至不能被欺骗/黑客攻击,因为实际值最终被赋予 Graphics.setColor() 而不是 Graphics2D.setPaint() (即使 Metal 是基于 Swing 的并且不是 AWT)死胡同。唯一的解决方案似乎是完全子类化 JButton。

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.

小…红帽 2024-12-07 11:39:29

我发现卢卡的回答是最好的。

我只是做了一些改变。我添加了一个淡入淡出变量,以便选择如果需要,可以不选择纯白色。

这是总代码:

 import java.awt.Color;
 import java.awt.GradientPaint;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Point;
 import javax.swing.JButton;
 import javax.swing.BorderFactory;
 
 public class GradientButton extends JButton
 {
     private float fade;
     
     public GradientButton(String text)
     {
         super(text);
         init(1.0f);
     }
     
     public GradientButton(String text, Color color, float fade)
     {
         super(text);
         init(fade);
         setBackground(color);
     }

     private void init(float fade)
     {
         setFade(fade);
         setContentAreaFilled(false);
         setBorder(BorderFactory.createRaisedBevelBorder());
     }
     
     public void setFade(float fade)
     {
         if(fade < 0)
             this.fade = 0;
         else if(fade > 1.0f)
             this.fade = 1.0f;
         else
             this.fade = fade;
     }
     
     @Override
     protected void paintComponent(Graphics g)
     {
         Color back = getBackground();
         int rb = back.getRed();
         int gb = back.getGreen();
         int bb = back.getBlue();
         
         int rf = (int)((255 - rb) * fade);
         int gf = (int)((255 - gb) * fade);
         int bf = (int)((255 - bb) * fade);
         
         Color fadeColor = new Color(rb + rf, gb + gf, bb + bf);
 
         int y = getInsets().top;
         int h = getHeight() - getInsets().top - getInsets().bottom;
         Graphics2D g2 = (Graphics2D)g.create();
         g2.setPaint(new GradientPaint(
                 new Point(0,y), 
                 getBackground(), 
                 new Point(0, h/3 + y), 
                 fadeColor));
         g2.fillRect(0, y, getWidth(), h/3);
         g2.setPaint(new GradientPaint(
                 new Point(0, h/3 + y), 
                 fadeColor,
                 new Point(0, h + y), 
                 getBackground()));
         g2.fillRect(0, h/3 + y, getWidth(), h);
         g2.dispose();
 
         super.paintComponent(g);
     }
     
     public void setFontSize(float size)
     {
         setFont(getFont().deriveFont(size));
     }
 }

luca's answer I found to be the best.

I just made a few changes. I added a fade variable for the option of not going to pure white if desired.

Here is the total code:

 import java.awt.Color;
 import java.awt.GradientPaint;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Point;
 import javax.swing.JButton;
 import javax.swing.BorderFactory;
 
 public class GradientButton extends JButton
 {
     private float fade;
     
     public GradientButton(String text)
     {
         super(text);
         init(1.0f);
     }
     
     public GradientButton(String text, Color color, float fade)
     {
         super(text);
         init(fade);
         setBackground(color);
     }

     private void init(float fade)
     {
         setFade(fade);
         setContentAreaFilled(false);
         setBorder(BorderFactory.createRaisedBevelBorder());
     }
     
     public void setFade(float fade)
     {
         if(fade < 0)
             this.fade = 0;
         else if(fade > 1.0f)
             this.fade = 1.0f;
         else
             this.fade = fade;
     }
     
     @Override
     protected void paintComponent(Graphics g)
     {
         Color back = getBackground();
         int rb = back.getRed();
         int gb = back.getGreen();
         int bb = back.getBlue();
         
         int rf = (int)((255 - rb) * fade);
         int gf = (int)((255 - gb) * fade);
         int bf = (int)((255 - bb) * fade);
         
         Color fadeColor = new Color(rb + rf, gb + gf, bb + bf);
 
         int y = getInsets().top;
         int h = getHeight() - getInsets().top - getInsets().bottom;
         Graphics2D g2 = (Graphics2D)g.create();
         g2.setPaint(new GradientPaint(
                 new Point(0,y), 
                 getBackground(), 
                 new Point(0, h/3 + y), 
                 fadeColor));
         g2.fillRect(0, y, getWidth(), h/3);
         g2.setPaint(new GradientPaint(
                 new Point(0, h/3 + y), 
                 fadeColor,
                 new Point(0, h + y), 
                 getBackground()));
         g2.fillRect(0, h/3 + y, getWidth(), h);
         g2.dispose();
 
         super.paintComponent(g);
     }
     
     public void setFontSize(float size)
     {
         setFont(getFont().deriveFont(size));
     }
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文