Is it possible to achieve automatic word wrap of text开发者_JAVA技巧s in JButtons? I am having few dynamic buttons which I create on runtime. I want to put word wrap feature on the buttons so that I can see some better test on buttons. Is it possible to do that?
This example uses Java's inbuilt CSS rendering abilities to to do the 'heavy lifting' of determining when to do a line break. It uses a JLabel
, but the same principles apply to any component that will render HTML.
FixedWidthText.java
import javax.swing.*;
class FixedWidthText {
public static void showLabel(int width, String units) {
String content1 = "<html>"
+ "<body style='background-color: white; width: ";
String content2 = "'>"
+ "<h1>Fixed Width</h1>"
+ "<p>Body width fixed at ";
String content3
= " using CSS. "
+ "Java's HTML"
+ " support includes support"
+ " for basic CSS.</p>";
final String content = content1 + width + units
+ content2 + width + units + content3;
Runnable r = () -> {
JLabel label = new JLabel(content);
JOptionPane.showMessageDialog(null, label);
};
SwingUtilities.invokeLater(r);
}
public static void main(String[] args) {
showLabel(160, "px");
showLabel(200, "px");
showLabel(50, "%");
}
}
Screen shots
160px
200px
50%
Use HTML...
button.setText("<html><center>"+"This is a"+"<br>"+"swing button"+"</center></html>");
The easiest thing to do is to modify another Component that supports word wrap so that it acts as a Button. I made a simple class which manipulates JTextArea to act as Button.
public class MultiLineButton extends JTextArea implements MouseListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private Color defaultColor;
private Color highlight, lightHighlight;
private BtnState state;
private List<ActionListener> actionListeners;
public MultiLineButton(String text, Color defaultColor) {
this.setEditable(false);
this.setText(text);
this.setLineWrap(true);
this.setWrapStyleWord(true);
this.addMouseListener(this);
this.setBorder(new EmptyBorder(5, 10, 5, 10));
state = BtnState.NORMAL;
this.defaultColor = defaultColor;
this.setBackground(defaultColor);
highlight = new Color(122, 138, 153);
lightHighlight = new Color(184, 207, 229);
// clickedColor = new Color(r, g, b);/
actionListeners = new ArrayList<>();
}
@Override
public Color getSelectionColor() {
return getBackground();
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
setBackground(lightHighlight);
state = BtnState.CLICKED;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
for (ActionListener l : actionListeners) {
l.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, this.getText()));
}
setBackground(defaultColor);
state = BtnState.NORMAL;
repaint();
}
@Override
public void mouseEntered(MouseEvent e) {
state = BtnState.HOVERED;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(defaultColor);
state = BtnState.NORMAL;
repaint();
}
@Override
public void paintBorder(Graphics g) {
super.paintBorder(g);
Graphics g2 = g.create();
g2.setColor(highlight);
switch (state) {
case NORMAL:
g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
break;
case HOVERED:
g2.drawRect(1, 1, getWidth() - 3, getHeight() - 3);
g2.setColor(lightHighlight);
g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2.drawRect(2, 2, getWidth() - 5, getHeight() - 5);
break;
case CLICKED:
Border b = new BevelBorder(BevelBorder.LOWERED);
b.paintBorder(this, g2, 0, 0, getWidth(), getHeight());
break;
}
g2.dispose();
}
public void addActionListener(ActionListener l) {
actionListeners.add(l);
}
public List<ActionListener> getActionListeners() {
return actionListeners;
}
}
BtnState is simply an enum with the Constants NORMAL, HOVERED, CLICKED
Most of the code is just used to make the JTextArea look like a JButton and it works quite fine. One drawback is that you loose the ability of modifying it via ButtonModels, but for the most applications this will be enough.
@Override
public void paint(Graphics pGraphics)
{
super.paint(pGraphics);
Graphics2D g2d = (Graphics2D) pGraphics;
FontRenderContext frc = g2d.getFontRenderContext();
String itemName = item.getName();
AttributedString attributedString = new AttributedString(itemName);
attributedString.addAttribute(TextAttribute.FONT, getFont());
AttributedCharacterIterator iterator = attributedString.getIterator();
LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, frc);
float wrappingWidth = getSize().width - 15;
StringBuilder stringBuilder = new StringBuilder("<html><center>");
int previousIndex = 0;
while (measurer.getPosition() < itemName.length())
{
if (previousIndex != 0) stringBuilder.append("<br>");
stringBuilder.append(itemName.substring(previousIndex, measurer.getPosition()));
previousIndex = measurer.getPosition();
measurer.nextLayout(wrappingWidth);
}
if (previousIndex < itemName.length())
{
if (previousIndex != 0) stringBuilder.append("<br>");
stringBuilder.append(itemName.substring(previousIndex));
}
stringBuilder.append("</center></html>");
setText(stringBuilder.toString());
}
精彩评论