Java JButton设置文本背景色

Java JButton set text background color

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

为了制作它我做了很多研究,我快完成了!

我选择使用圆角边框,因为否则对我来说似乎不可能:/(我是 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);
    }

}

提前感谢您的回复:)

Border不填。所以一旦你让你的组件透明(setOpaque(false))你就会失去背景颜色,但是无论如何你都会遇到组件绘制背景区域内的边框绘制的奇怪问题。

没有简单的方法可以做到这一点,事实上(对于 Swing)一个“通常”更好的解决方案是在外观和感觉级别上执行此操作(您将获得最终控制权并可以更改所有按钮在 UI 中,无需更改他们使用的代码,因为 , 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 委托供所有按钮使用

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

package Whosebug;

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(), "Whosebug.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(), "Whosebug.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 委托,您必须提供 完全限定的 class 名称,即完整的包路径和 class 名字。

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