0

When I add border to my button, the button shrinks in size. I am using the following line to add the border:

jButton.setBorder(BorderFactory.createLineBorder(Color.RED));

This is my button without border:

Button without border

This is my button with border:

enter image description here

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
Muhammad Umer
  • 69
  • 1
  • 11

3 Answers3

2

If you want to add a border, and also want a margin between the label text and the edge of the border, create a compound border, with an empty border on the inside (with the proper size fot the margin) and do n ot set the preferred size. This will allow the button to size itself properly regardless of the text and font of the label. For example:

LineBorder border1 = new LineBorder(Color.red);
EmptyBorder border2 = new EmptyBorder(1,5,1,5);
Border newBorder = BorderFactory.createCompoundBorder(border1, border2);
FredK
  • 4,094
  • 1
  • 9
  • 11
  • your solution is not working, it gives the same output as before – Muhammad Umer Aug 23 '18 at 18:32
  • Hey, it still gives a small button and I have to edit the insets for the empty border to get a bigger button which is the same thing as setting a preferred size. Thanks anyways – Muhammad Umer Aug 23 '18 at 19:04
  • @MuhammadUmer Actually, it's not (the same as setting the preferred size) - Change the text dynamically, or change the font, this solution will adapt, the other won't – MadProgrammer Aug 23 '18 at 20:15
1

A quick a dirty example of why setPreferredSize is a terrible idea and why you should avoid it as much as possible.

You can also have a look at Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more of discussion on the subject

NormalExaggerated

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton goodButton = new JButton("Location 1");
            Insets insets = goodButton.getInsets();
            goodButton.setBorder(new CompoundBorder(
                            new LineBorder(Color.RED),
                            new EmptyBorder(insets)));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(8, 8, 8, 8);
            add(goodButton, gbc);

            JButton badButton = new JButton("Location 2");
            badButton.setPreferredSize(new Dimension(110, 29));
            badButton.setBorder(new LineBorder(Color.RED));
            add(badButton, gbc);

            ActionListener listener = new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    goodButton.setText(random());
                    badButton.setText(random());

                    float size = rnd.nextInt(48) + 12;

                    Font f = goodButton.getFont().deriveFont(size);
                    goodButton.setFont(f);
                    badButton.setFont(f);
                }
            };

            goodButton.addActionListener(listener);
            badButton.addActionListener(listener);
        }

        private Random rnd = new Random();

        protected String random() {
            int length = rnd.nextInt(15) + 5;
            StringBuilder sb = new StringBuilder(length);
            for (int index = 0; index < length; index++) {
                sb.append((char)('A' + rnd.nextInt(26)));
            }
            return sb.toString();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

    }


}

This is some what of an exaggerated example, but I was, unfortunate enough, to inherit a project where the previous developer use setPreferredSize and while it worked "ok" on same PCs running the same OS, we had countless, seemingly random issues and many more and don't even get me started on what it did on MacOS.

But I'm only developing for Windows

Big deal, as I said, we had the app working "ok" on some Windows PCs, but as soon as some one had custom DPIs or font metrics or they upgraded to new version of Windows, it began to fall apart - Short answer - don't use setPreferredSize

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
-1

Define width and height as per your need and implement the following line of code:

jButton.setPreferredSize(new Dimension(width, height));
Partho KR
  • 112
  • 2
  • 10
  • (1-) This is NOT the proper solution. Swing components are designed to determine there own preferred size based on the properties of the component (font, text border etc.). – camickr Aug 24 '18 at 00:21