如何在 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);
    }
}