Java JButton 设置文本背景颜色

Posted

技术标签:

【中文标题】Java JButton 设置文本背景颜色【英文标题】:Java JButton set text background color 【发布时间】:2022-01-22 12:23:56 【问题描述】:

我必须创建一个具有精确颜色的圆形按钮。

为了实现它,我做了很多研究,我快到了!

我选择使用圆形边框,因为否则对我来说似乎是不可能的:/(我是 Java 新手)。

所以我只需要找到一种方法将按钮内容(文本)的背景设​​置为正确的颜色,我就完成了。 (我目前只有边框并禁用背景以查看圆形部分,因此文本的背景为空......)

结果:

预期结果:

我已经尝试过论文:

Complex solution I didn't understand and that doesn't seem to work 我还尝试了 Java 主题的解决方案
package components;

import java.awt.Font;
import java.awt.Component;

import javax.swing.BorderFactory;
import javax.swing.JButton;

import utils.BrandColors;

public class Button extends JButton 

    private int xPadding = 10;

    public Button(String text) 
        super(text);
        this.init();
    

    private void init() 
        this.setFont(new Font("Arial", Font.PLAIN, 16));
        this.setForeground(BrandColors.TEXT_ON_SECOUNDARY);

        this.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(BrandColors.SECOUNDARY, 15, true),
            BorderFactory.createMatteBorder(0, this.xPadding, 0, this.xPadding, BrandColors.SECOUNDARY)
        ));

        // this.setBackground(BrandColors.SECOUNDARY);
        this.setOpaque(false);
    


提前感谢您的回复:)

【问题讨论】:

使用this.setBackground(BrandColors.SECOUNDARY); 是设置文本/按钮背景颜色的正确方法。 @sorfiend 是的,但是这样做会使圆形边框消失。 Sooo,您遇到的“核心”问题是,组件不是圆形的,它们是矩形的。边框不填。他们通常只绘制边框。所以如果你想要一个“填充”的“圆角矩形”,你将不得不挽起袖子弄脏 @MadProgrammer 如果没有其他办法,我会去的,但我什至不知道该寻找什么...... 【参考方案1】:

Border 不要填写。因此,一旦您使组件透明 (setOpaque(false)),您将失去背景颜色,但无论如何您都会在组件的绘制背景区域内绘制边框时遇到奇怪的问题。

没有简单的方法可以做到这一点,事实上(对于 Swing)一个“一般”更好的解决方案是在外观和感觉级别上做到这一点(您可以获得最终控制并可以更改所有按钮UI 无需更改他们使用的代码?,用于example、example、example)

但是我没有时间处理所有这些,所以,相反,我将直接使用“自定义绘制,自定义组件”路线。

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        public TestPane() 
            setBorder(new EmptyBorder(32, 32, 32, 32));
            setLayout(new GridBagLayout());
            add(new Button("This is a test"));
        

    

    public class BrandColors 

        public static final Color TEXT_ON_SECOUNDARY = Color.WHITE;
        public static final Color SECOUNDARY = Color.RED;
    

    public class Button extends JButton 

        private int xPadding = 10;

        public Button(String text) 
            super(text);
            this.init();
        

        private void init() 
            this.setFont(new Font("Arial", Font.PLAIN, 16));
            this.setForeground(BrandColors.TEXT_ON_SECOUNDARY);

            this.setContentAreaFilled(false);
            this.setBorderPainted(false);

            this.setBackground(BrandColors.SECOUNDARY);
            this.setOpaque(false);
        

        @Override
        protected void paintComponent(Graphics g) 
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
            );
            g2d.setRenderingHints(hints);
            g2d.setColor(getBackground());
            g2d.fill(new RoundRectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1, 15, 15));
            g2d.setColor(getForeground());
            super.paintComponent(g2d);
            g2d.dispose();
        

    

现在,这里的诀窍在于知道paintComponent 也会渲染文本,所以我们需要在调用super.paintComponent 之前绘制背景

UI 委托示例...

现在,Swing 的特点之一是它的“可插拔外观和感觉”。这允许您修改组件的“外观和感觉”,而无需修改其余代码。

以下示例显示了为 JButton 的特定实例设置 UI 委托的方法

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicButtonUI;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        public TestPane() 
            setBorder(new EmptyBorder(32, 32, 32, 32));
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(4, 4, 4, 4);

            JButton button = new JButton("This is a normal button");
            add(button, gbc);
            JButton superButton = new JButton("This is a super button");
            superButton.setUI(new RoundedButtonUI());
            add(superButton, gbc);
        

    

    public class BrandColors 
        public static final Color TEXT_ON_SECOUNDARY = Color.WHITE;
        public static final Color SECOUNDARY = Color.RED;
    

    public class RoundedButtonUI extends BasicButtonUI 
        @Override
        protected void installDefaults(AbstractButton b) 
            super.installDefaults(b);
            b.setOpaque(false);
            b.setBackground(BrandColors.SECOUNDARY);
            b.setForeground(BrandColors.TEXT_ON_SECOUNDARY);
        

        @Override
        public void paint(Graphics g, JComponent c) 
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
            );
            g2d.setRenderingHints(hints);
            g2d.setColor(c.getBackground());
            g2d.fill(new RoundRectangle2D.Double(0, 0, c.getWidth() - 1, c.getHeight() - 1, 15, 15));
            g2d.setColor(c.getForeground());
            super.paint(g, c);
            g2d.dispose();
        

    

影响 UI 中的所有按钮

如果您想更改 UI 中的所有按钮,而无需更改任何相关代码,您可以将 UI 委托设置为所有按钮使用的默认 UI 委托

为此,我必须进行一些额外的更改。首先,委托类需要在它自己的文件中(请注意包名),我必须实现static方法createUI

package ***;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;

public class RoundedButtonUI extends BasicButtonUI 

    private static RoundedButtonUI shared;

    public static ComponentUI createUI(JComponent c) 
        if (shared != null) 
            return shared;
        
        shared = new RoundedButtonUI();
        return shared;
    

    @Override
    protected void installDefaults(AbstractButton b) 
        super.installDefaults(b);
        b.setOpaque(false);
        b.setBackground(BrandColors.SECOUNDARY);
        b.setForeground(BrandColors.TEXT_ON_SECOUNDARY);
    

    @Override
    public void paint(Graphics g, JComponent c) 
        Graphics2D g2d = (Graphics2D) g.create();
        RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHints(hints);
        g2d.setColor(c.getBackground());
        g2d.fill(new RoundRectangle2D.Double(0, 0, c.getWidth() - 1, c.getHeight() - 1, 15, 15));
        g2d.setColor(c.getForeground());
        super.paint(g, c);
        g2d.dispose();
    


现在,在你做任何其他事情之前,我需要安装它,UIManager.getDefaults().put(new JButton().getUIClassID(), "***.RoundedButtonUI");。这应该在您调用任何其他与 UI 相关的代码之前完成(以及在您设置外观之后,如果您正在这样做的话)

然后我就可以正常运行代码了

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                UIManager.getDefaults().put(new JButton().getUIClassID(), "***.RoundedButtonUI");
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        public TestPane() 
            setBorder(new EmptyBorder(32, 32, 32, 32));
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(4, 4, 4, 4);

            JButton button = new JButton("This is a normal button");
            add(button, gbc);
            JButton superButton = new JButton("This is a super button");
            add(superButton, gbc);
        

    


请注意

要以这种方式安装新的 UI 委托,您必须提供完全限定类名,即完整的包路径和类名。

在我上面的例子中,我使用***作为我的包名(我很懒),所以安装看起来像UIManager.getDefaults().put(new JButton().getUIClassID(), "***.RoundedButtonUI");

【讨论】:

以上是关于Java JButton 设置文本背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

JButton、JTextFeild、JLabel 设置背景颜色不起作用

如何将所有 JButton 的默认鼠标按下背景颜色覆盖为其当前背景颜色的较暗阴影?

Eclipse详细设置护眼背景色和字体颜色并导出

如何在 Java 中为 word 文档(.doc 或 .docx)设置背景颜色(页面颜色)?

为什么我的JPanel背景颜色不会改变?

修改mac系统的文本的大小以及背景颜色