【发布时间】:2011-08-11 14:11:40
【问题描述】:
是否可以在JButtons中实现文本自动换行?我在运行时创建的动态按钮很少。我想在按钮上添加自动换行功能,以便我可以看到一些更好的按钮测试。有可能吗?
【问题讨论】:
-
我不知道如何自动执行此操作,但如下所示,您可以使用 HTML 代码手动执行此操作,
也可以。
是否可以在JButtons中实现文本自动换行?我在运行时创建的动态按钮很少。我想在按钮上添加自动换行功能,以便我可以看到一些更好的按钮测试。有可能吗?
【问题讨论】:
也可以。
此示例使用 Java 的内置 CSS 呈现功能来完成确定何时进行换行的“繁重工作”。它使用JLabel,但同样的原则适用于任何将呈现 HTML 的组件。
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, "%");
}
}
【讨论】:
使用 HTML...
button.setText("<html><center>"+"This is a"+"<br>"+"swing button"+"</center></html>");
【讨论】:
最简单的做法是修改另一个支持自动换行的组件,使其充当按钮。我做了一个简单的类来操作 JTextArea 来充当 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 只是一个带有常量 NORMAL、HOVERED、CLICKED 的枚举
大部分代码只是用来使 JTextArea 看起来像一个 JButton,它工作得很好。一个缺点是您失去了通过 ButtonModels 修改它的能力,但对于大多数应用程序来说,这已经足够了。
【讨论】:
@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());
}
【讨论】: