在Java图形用户界面编程中,经常需要处理文本的显示。标准的Label组件虽然简单,但它不支持文本的自动换行和对齐方式的自定义。为了解决这个问题,可以创建一个自定义的组件,比如VWrappingLabel,它不仅能够自动换行以适应组件的宽度,还能支持文本的垂直和水平对齐。
VWrappingLabel是基于Symantec的WrappingLabel类进行扩展的。它不仅能够处理文本的垂直格式化,还能在标签文本中嵌入的换行符处进行换行。这个自定义组件的关键在于使用setText()方法在代码中设置标签的文本,而不是在设计时的属性列表窗口中设置文本。否则,Visual Café会将"\n"替换为"\\n"。
VWrappingLabel类还提供了设置文本水平和垂直对齐方式的方法,分别是setHAlignStyle()和setVAlignStyle()。此外,还可以通过构造函数来设置对齐方式。
以下是VWrappingLabel类的实现代码:
public class VWrappingLabel extends Canvas {
protected String text;
protected float m_nHAlign;
protected float m_nVAlign;
protected int baseline;
protected FontMetrics fm;
public VWrappingLabel() {
this("");
}
public VWrappingLabel(String s) {
this(s, Canvas.LEFT_ALIGNMENT, Canvas.CENTER_ALIGNMENT);
}
public VWrappingLabel(String s, float nHorizontal, float nVertical) {
setText(s);
setHAlignStyle(nHorizontal);
setVAlignStyle(nVertical);
}
public float getHAlignStyle() {
return m_nHAlign;
}
public float getVAlignStyle() {
return m_nVAlign;
}
public String getText() {
return text;
}
public void setHAlignStyle(float a) {
m_nHAlign = a;
invalidate();
}
public void setVAlignStyle(float a) {
m_nVAlign = a;
invalidate();
}
public void setText(String s) {
text = s;
repaint();
}
public String paramString() {
return "";
}
public void paint(Graphics g) {
if (text != null) {
Dimension d;
int currentY = 0;
Vector lines;
fm = getFontMetrics(getFont());
baseline = fm.getMaxAscent();
d = getSize();
lines = breakIntoLines(text, d.width);
if (m_nVAlign == V_ALIGN_CENTER) {
int center = (d.height / 2);
currentY = center - ((lines.size() / 2) * fm.getHeight());
} else if (m_nVAlign == V_ALIGN_BOTTOM) {
currentY = d.height - (lines.size() * fm.getHeight());
}
Enumeration elements = lines.elements();
while (elements.hasMoreElements()) {
drawAlignedString(g, (String) (elements.nextElement()), 0, currentY, d.width);
currentY += fm.getHeight();
}
fm = null;
}
}
protected Vector breakIntoLines(String s, int width) {
int fromIndex = 0;
int pos = 0;
int bestpos;
String largestString;
Vector lines = new Vector();
while (fromIndex != -1) {
while (fromIndex < text.length() && text.charAt(fromIndex) == ' ') {
++fromIndex;
if (fromIndex >= text.length()) break;
}
pos = fromIndex;
bestpos = -1;
largestString = null;
while (pos >= fromIndex) {
boolean bHardNewline = false;
int newlinePos = text.indexOf("\n", pos);
int spacePos = text.indexOf(" ", pos);
if (newlinePos != -1 && ((spacePos == -1) || (spacePos != -1 && newlinePos < spacePos))) {
pos = newlinePos;
bHardNewline = true;
} else {
pos = spacePos;
bHardNewline = false;
}
if (pos == -1) {
s = text.substring(fromIndex);
} else {
s = text.substring(fromIndex, pos);
}
if (fm.stringWidth(s) < width) {
largestString = s;
bestpos = pos;
if (bHardNewline) bestpos++;
if (pos == -1 || bHardNewline) break;
} else {
break;
}
++pos;
}
if (largestString == null) {
int totalWidth = 0;
int oneCharWidth = 0;
pos = fromIndex;
while (pos < text.length()) {
oneCharWidth = fm.charWidth(text.charAt(pos));
if ((totalWidth + oneCharWidth) >= width) break;
totalWidth += oneCharWidth;
++pos;
}
lines.addElement(text.substring(fromIndex, pos));
fromIndex = pos;
} else {
lines.addElement(largestString);
fromIndex = bestpos;
}
}
return lines;
}
protected void drawAlignedString(Graphics g, String s, int x, int y, int width) {
int drawx;
int drawy;
drawx = x;
drawy = y + baseline;
if (m_nHAlign != Canvas.LEFT_ALIGNMENT) {
int sw;
sw = fm.stringWidth(s);
if (m_nHAlign == Canvas.CENTER_ALIGNMENT) {
drawx += (width - sw) / 2;
} else if (m_nHAlign == Canvas.RIGHT_ALIGNMENT) {
drawx = drawx + width - sw;
}
}
g.drawString(s, drawx, drawy);
}
}