Home > Back-end >  Java JButton set text background color
Java JButton set text background color

Time:12-21

I have to create a rounded button with a precise color.

I did a lot of research in order to make it and I'm almost there!

I choose to use a rounded border because doing otherwise seem impossible to me :/ (I'm new to Java).

So I just need to find a way to set the background of the content of the button (the text) the right color and I'm done. (I currently have just the border and disabled the background in order to see the rounded part so the background of the text is empty...)

Result :

result

Expected result :

expected result

I've already tried theses :

  • enter image description here

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

    Now, the trick here is in knowing that paintComponent will also render the text, so we need to paint the background BEFORE we call super.paintComponent

    UI delegate example...

    Now, one of the features of Swing is it's "pluggable look and feel". This allows you to modify the "look and feel" of components without having to modify the rest of the code.

    The following example shows away to set a UI delegate for a specific instance of JButton

    enter image description here

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

    Effect ALL buttons in the UI

    If you want to change ALL the buttons in the UI, without having to change any of the related code, you can set the UI delegate as the default UI delegate to be used by all buttons

    To do this, I had to make a couple of additional changes. First, the delegate class needs to be in it's own file (please take note of the package name) and I had to implement the static method createUI

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

    Now, before I anything else, I need to install it, UIManager.getDefaults().put(new JButton().getUIClassID(), "stackoverflow.RoundedButtonUI");. This should be done before you call any other UI related code (and after you've set the look and feel, if you're doing that)

    And then I can just run the code as normal

    enter image description here

    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(), "stackoverflow.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);
            }
    
        }
    
    }
    

    PLEASE NOTE

    In order to install a new UI delegate this way, you MUST supply the fully qualified class name, that is, the full package path AND the class name.

    In my examples above, I'm using stackoverflow as my package name (I'm lazy), so the installation looks like UIManager.getDefaults().put(new JButton().getUIClassID(), "stackoverflow.RoundedButtonUI");

  • Related