7

How do you resize a JButton at runtime so it adapts to the text given by setSize? I've done some searching and this is the code I've come up with so far. Could this be turned into a utility method?

FontMetrics metrics = getFontMetrics( font );
int width = metrics.stringWidth( string );

P.S: No layout manager is being used.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
James P.
  • 19,313
  • 27
  • 97
  • 155

2 Answers2

9

You need to use setPreferredSize() on the component. Then, to resize it, call setBounds().

I would probably subclass the button, and override the setText(String text) method to include the resizing code.

@Override
public void setText(String arg0) {
    super.setText(arg0);
    FontMetrics metrics = getFontMetrics(getFont()); 
    int width = metrics.stringWidth( getText() );
    int height = metrics.getHeight();
    Dimension newDimension =  new Dimension(width+40,height+10);
    setPreferredSize(newDimension);
    setBounds(new Rectangle(
                   getLocation(), getPreferredSize()));
}

For testing, I did this in the constructor of my new JButton subclass:

public ResizeToTextButton(String txt){
    super(txt);
    addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            setText(JOptionPane.showInputDialog("Text"));
        }
    });
}

So, whenever I clicked on the button I could change the text and see if it resized properly.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 2
    The line: "FontMetrics metrics = getFontMetrics(new Font(Font.SANS_SERIF, Font.PLAIN, 12));" should say: "FontMetrics metrics = getFontMetrics(getFont());", but thanks a lot for this one. :-) – AudioDroid Dec 13 '10 at 22:01
  • I should also say thank you. This should be particularly useful for applications that can be displayed in more than one language. – James P. Dec 16 '10 at 05:40
  • This can't be the accepted answer. I'm here because I need to know the right way as well, but I know for a fact this answer is the wrong way to do it. The problem with this answer is that this does not take into account alterations to the UI that do not involve setting the text (i.e. resizing, in which case this could affect the text width and height). Also, way more troubling than that, is getFontMetrics requires a graphics Object, which does not exist until the Object is drawn. If you set the text before the Object is drawn (even if you handle the NPE that you have), then this does nothing. – searchengine27 Aug 18 '15 at 23:12
2

I had the same problem, even when using a layout manager (BorderLayout). But in my case a simple call to layoutContainer() of the associated layout manager and then a repaint() on the JFrame was sufficient for changing the width of the button.

button1.setText("New Label that differs in width");
// button1 is inside the container horizontalBox
horizontalBox.getLayout().layoutContainer(horizontalBox);
repaint(); // on the containing JFrame