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 extendingJButton
and overriding its paint method. In that method, you would tokenize your string based onn
, 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 ofJLabels
and theJButton
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! | |
---|---|
|