如何在 AWT 中创建换行和/或多行标签。





5.00/5 (1投票)
2001 年 8 月 13 日
1分钟阅读

72883
如何在 AWT 中创建换行和/或多行标签
引言
VWrappingLabel
基于 Symantec 的 WrappingLabel
。以下摘自 Daniel Kirkdorffers Visual Cafe Tips,这是最初发现这段代码的地方的一段简短描述。
Symantec 的 WrappingLabel
是一个非常方便的组件。除了能够自动换行标签文本以适应组件的宽度之外,WrappingLabel
还可以作为基本 Label
组件的一个很好的替代品,在您想要修改标签的前景色或背景色时使用。
许多人询问 WrappingLabel
是否可以考虑换行符“\n”在换行时强制换行。不幸的是,WrappingLabel
会忽略换行符。但是,为了响应这种兴趣,Paul Williams 编写了 WrappingLabel
的另一个版本,该版本可以处理换行符。我拥有源代码、编译后的类文件和 .desc 描述文件的副本。在 Visual Café 中使用此组件的关键是在代码中使用 setText()
方法设置标签的文本,而不是在设计时在属性列表窗口中设置文本。否则,Visual Café 会将“\n”替换为“\\n”。Paul 还添加了一个很好的功能,即通过 setHAlignStyle()
和 setVAlignStyle()
方法或通过替代构造函数设置文本的水平和垂直对齐方式。
感谢 Paul Williams,他曾就职于 Criterion Inc. 我试图联系您,但似乎您的旧电子邮件地址已经失效了。我保证我只做了一些小的修改。
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Dimension;
import java.awt.Label;
import java.util.Vector;
import java.util.Enumeration;
/**
* VWrappingLabel is based on Symantec's class WrappingLabel; however, this
class
* can format the text vertically, too. It also wraps text at newlines
embedded
* in the label's text.
*
* @see symantec.awt.WrappingLabel
* @author Paul F. Williams (mailto:paul@criterioninc.com)
* Criterion, Inc. (http://www.criterioninc.com)
* @author Kyle Morris (mailto:morriskg@nexusfusion.com)
*
*/
public class VWrappingLabel extends Canvas
{
//--------------------------------------------------
// constants
//--------------------------------------------------
//--------------------------------------------------
// class variables
//--------------------------------------------------
//--------------------------------------------------
// member variables
//--------------------------------------------------
protected String text;
protected float m_nHAlign;
protected float m_nVAlign;
protected int baseline;
protected FontMetrics fm;
//--------------------------------------------------
// constructors
//--------------------------------------------------
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);
}
//--------------------------------------------------
// accessor members
//--------------------------------------------------
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();
}
//--------------------------------------------------
// member methods
//--------------------------------------------------
public String paramString()
{
return "";
}
public void paint(Graphics g)
{
if (text != null)
{
Dimension d;
int currentY = 0;
Vector lines;
// Set up some class variables
fm = getFontMetrics(getFont());
baseline = fm.getMaxAscent();
// Get the maximum height and width of the current control
d = getSize();
lines = breakIntoLines (text, d.width);
//if (m_nVAlign == V_ALIGN_CENTER)
if (m_nVAlign == Canvas.CENTER_ALIGNMENT)
{
int center = (d.height / 2);
currentY = center - ( (lines.size() / 2) * fm.getHeight() );
}
//else if (m_nVAlign == V_ALIGN_BOTTOM)
else if (m_nVAlign == Canvas.BOTTOM_ALIGNMENT)
{
currentY = d.height - ( lines.size() * fm.getHeight() );
}
// now we have broken into substrings, print them
Enumeration elements = lines.elements();
while (elements.hasMoreElements())
{
drawAlignedString(g,
(String)(elements.nextElement()),
0, currentY, d.width);
currentY += fm.getHeight();
}
// We're done with the font metrics...
fm = null;
}
}
protected Vector breakIntoLines (String s, int width)
{
int fromIndex = 0;
int pos = 0;
int bestpos;
String largestString;
Vector lines = new Vector();
// while we haven't run past the end of the string...
while (fromIndex != -1)
{
// Automatically skip any spaces at the beginning of the line
while (fromIndex < text.length()
&& text.charAt(fromIndex) == ' ')
{
++fromIndex;
// If we hit the end of line
// while skipping spaces, we're done.
if (fromIndex >= text.length()) break;
}
// fromIndex represents the beginning of the line
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 && // there is a newline and either
((spacePos == -1) || // 1. there is no space, or
(spacePos != -1 &&
newlinePos < spacePos)))
// 2. the newline is first
{
pos = newlinePos;
bHardNewline = true;
}
else
{
pos = spacePos;
bHardNewline = false;
}
// Couldn't find another space?
if (pos == -1)
{
s = text.substring(fromIndex);
}
else
{
s = text.substring(fromIndex, pos);
}
// If the string fits, keep track of it.
if (fm.stringWidth(s) < width)
{
largestString = s;
bestpos = pos;
// If we've hit the end of the
// string or a newline, use it.
if (bHardNewline)
bestpos++;
if (pos == -1 || bHardNewline) break;
}
else
{
break;
}
++pos;
}
if (largestString == null)
{
// Couldn't wrap at a space, so find the largest line
// that fits and print that. Note that this will be
// slightly off -- the width of a string will not necessarily
// be the sum of the width of its characters, due to kerning.
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);
}
}