A multiline button is possible!

Can JButton create a multiline button?

Q: Suppose I want to create the button with a label as shown below:

"Your

Name"

"Name" will be on the second line.

I tried to create it with:

new JButton("Your \\n Name")

Unfortunately, that doesn't work. Do you have any suggestions?

A: The short answer: you can't do it without a bit of work on your part. The JButton does not intrinsically have the ability to wrap long lines or start a new line when the text contains a \n.

All JFC components are rendered through a corresponding ComponentUI. Instead of putting all of the rendering code in the JButton's paint method, the JButton delegates its display to a ButtonUI (an extension of ComponentUI). The ComponentUI allows us to change the look and feel of a Java Swing GUI on the fly by simply swapping in new ComponentUI renderers into our JComponents.

One implementation of ButtonUI that a JButton may use is the BasicButtonUI. If you're brave enough to look at the BasicButtonUI's code, you'll notice the method:

protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text)

paintText() does all the string drawing dirty work. If we dig a little further, you'll see that this method further delegates the actual drawing to the drawString() method in BasicGraphicsUtils:

public static void drawString(Graphics g,String text,int underlinedChar,int x,int y)

drawString() does a little processing and then simply calls the Graphics-based drawString() method. We had to dig a bit, but now it's fairly obvious why JButton won't wrap text around a new line.

So, to do what you want to do, you have a few choices:

  • You can create your own custom JButton by extending JButton and overriding its paint method. In that method, you would tokenize your string based on \n, do a few spacing calculations, draw your button, and then draw your broken text. However, if you do it that way, your button will lose its pluggable look and feel. You will also lose many of the other Swing display tricks.
  • You can create a new ButtonUI that formats your text properly.
  • You can forget about getting that functionality directly from the JButton. Instead, a combination of JLabels and the JButton will give you what you need. Try the following:

       JButton b = new JButton();
       b.setLayout(new BorderLayout());
       JLabel label1 = new JLabel("Your");
       JLabel label2 = new JLabel("Name");
       b.add(BorderLayout.NORTH,label1);
       b.add(BorderLayout.SOUTH,label2);
    

If you find that a multiline button is something you use a lot, you can wrap the above solution into a convenience class, say MultiLineButton. That class would extend JButton, encapsulate two JLabel instances, and have void setLabel1Text(String text) and void setLabel2Text(String text) methods.

 HTML rendering in Swing is possible!  

It appears that my original answer to the multiline button question was not complete. When I wrote my original answer to the multiline button question I was using Java 1.1.7 and Swing 1.0.3, for which my answer remains valid. Many developers (myself included) are stuck using these older versions. However, it appears that newer versions of Swing do enable HTML rendering.

Here are two suggestions sent in by two of JavaWorld's many astute readers:

Quite a few Swing components can render their contents with an HTML renderer. As a result, you can create a multiline button with the following code:

JButton b = new JButton("

Your
Name");

-- Sebastian Fernandez

AND

To solve the multiline button problem, simply write:

JButton myButton = new JButton("

Hello

World

");

Be aware that all Swing components now support HTML.

-- Tarek Hammoud

Tony Sintes is a senior consultant at ObjectWave, specializing in telecommunications. Tony has worked with Java since 1997 and is a Sun-certified Java 1.1 programmer and Java 2 developer.
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more