【问题标题】:Calculate the display width of a string in Java用Java计算字符串的显示宽度
【发布时间】:2010-09-20 11:38:06
【问题描述】:

Java中如何计算字符串的长度(以像素为单位)?

最好不使用 Swing。

编辑: 我想在 Java2D 中使用 drawString() 绘制字符串 并使用长度进行自动换行。

【问题讨论】:

  • 没有 Swing?你用的是什么设备?什么字体?什么尺寸?什么风格?所有这些都会改变显示宽度。
  • 你打算怎么画字符串?与 AWT?还是使用其他工具包?以像素为单位的字符串大小取决于稍后将绘制像素的绘图 API(当然还有您使用的字体、字体大小以及字体是否为粗体/斜体等)。如果不知道绘图 API 和字体属性,字符串就没有大小。
  • @S.洛特。你有它在一个。我很想把这个作为一个非问题来结束。
  • @David Arno:我在 n00bz 上是个软弱的人。我将添加 [beginner] 标签。
  • 对于 .NET 等效项有 TextRenderer 类,请参阅 stackoverflow.com/questions/604298/…

标签: java string-length


【解决方案1】:

我个人正在寻找可以让我计算多行字符串区域的东西,因此我可以确定给定区域是否足够大以打印字符串 - 保留特定字体。

private static Hashtable hash = new Hashtable();
private Font font;
private LineBreakMeasurer lineBreakMeasurer;
private int start, end;

public PixelLengthCheck(Font font) {
    this.font = font;
}

public boolean tryIfStringFits(String textToMeasure, Dimension areaToFit) {
    AttributedString attributedString = new AttributedString(textToMeasure, hash);
    attributedString.addAttribute(TextAttribute.FONT, font);
    AttributedCharacterIterator attributedCharacterIterator =
            attributedString.getIterator();
    start = attributedCharacterIterator.getBeginIndex();
    end = attributedCharacterIterator.getEndIndex();

    lineBreakMeasurer = new LineBreakMeasurer(attributedCharacterIterator,
            new FontRenderContext(null, false, false));

    float width = (float) areaToFit.width;
    float height = 0;
    lineBreakMeasurer.setPosition(start);

    while (lineBreakMeasurer.getPosition() < end) {
        TextLayout textLayout = lineBreakMeasurer.nextLayout(width);
        height += textLayout.getAscent();
        height += textLayout.getDescent() + textLayout.getLeading();
    }

    boolean res = height <= areaToFit.getHeight();

    return res;
}

【讨论】:

    【解决方案2】:

    现在,完全不同了。以下假设 arial 字体,并根据字符与宽度的线性插值进行疯狂猜测。

    // Returns the size in PICA of the string, given space is 200 and 'W' is 1000.
    // see https://p2p.wrox.com/access/32197-calculate-character-widths.html
    
    static int picaSize(String s)
    {
        // the following characters are sorted by width in Arial font
        String lookup = " .:,;'^`!|jl/\\i-()JfIt[]?{}sr*a\"ce_gFzLxkP+0123456789<=>~qvy$SbduEphonTBCXY#VRKZN%GUAHD@OQ&wmMW";
        int result = 0;
        for (int i = 0; i < s.length(); ++i)
        {
            int c = lookup.indexOf(s.charAt(i));
            result += (c < 0 ? 60 : c) * 7 + 200;
        }
        return result;
    }
    

    有趣,但可能不太实用。

    【讨论】:

      【解决方案3】:

      如果您只想使用 AWT,则使用Graphics.getFontMetrics(可选地指定字体,对于非默认字体)获取FontMetrics,然后使用FontMetrics.stringWidth 查找指定字符串的宽度。

      例如,如果您有一个名为 gGraphics 变量,您可以使用:

      int width = g.getFontMetrics().stringWidth(text);
      

      对于其他工具包,您需要向我们提供更多信息 - 它总是依赖于工具包。

      【讨论】:

      • 如果你提供一个示例用法可能会更清楚,最初我尝试将它用作静态方法,因为你是这样写的。
      • 已弃用!但仍然是最好的方法!,当没有更好的方法时,为什么他们不推荐使用方法!!!我就是不明白!
      • @Zich:我不确定你说的哪种方法已被弃用——据我所知,它们都没有在 Java 8 文档中被标记为弃用......
      • @Zich:这是Graphics 中的方法,而不是FontMetrics。但是你打电话给Toolkit.getFontMetrics,这确实被弃用了,这不是这个方法所说的......你需要非常小心这种事情,特别是在你开始谈论报告错误之前......
      • @Zich:嗯,我猜不到——我会使用非弃用方法,或者Toolkit.getFontMetrics 建议的非弃用方法。
      【解决方案4】:

      它并不总是需要依赖于工具包,或者并不总是需要使用 FontMetrics 方法,因为它需要首先获取 Web 容器或无头环境中不存在的图形对象。

      我已经在 web servlet 中对此进行了测试,它确实计算了文本宽度。

      import java.awt.Font;
      import java.awt.font.FontRenderContext;
      import java.awt.geom.AffineTransform;
      
      ...
      
      String text = "Hello World";
      AffineTransform affinetransform = new AffineTransform();     
      FontRenderContext frc = new FontRenderContext(affinetransform,true,true);     
      Font font = new Font("Tahoma", Font.PLAIN, 12);
      int textwidth = (int)(font.getStringBounds(text, frc).getWidth());
      int textheight = (int)(font.getStringBounds(text, frc).getHeight());
      

      为这些尺寸添加必要的值以创建所需的边距。

      【讨论】:

      • 我不认为以这种方式创建 affineTransform 和 fontRenderContext 会产生良好的行为。我猜 font.getTransfrom() 会更合乎逻辑。
      • 您的示例仍在使用 AWT 功能。例如,使用 SWT 字体,它不会工作,这就是为什么“它总是依赖于工具包”
      • @Olofu Mark - getStringBounds 只给出逻辑界限。为了使它更好,它应该使用 getBounds() 和 LineMetrics 对象来检索实际高度,包括 ascent+descent。
      【解决方案5】:

      在下面的类中使用getWidth方法:

      import java.awt.*;
      import java.awt.geom.*;
      import java.awt.font.*;
      
      class StringMetrics {
      
        Font font;
        FontRenderContext context;
      
        public StringMetrics(Graphics2D g2) {
      
          font = g2.getFont();
          context = g2.getFontRenderContext();
        }
      
        Rectangle2D getBounds(String message) {
      
          return font.getStringBounds(message, context);
        }
      
        double getWidth(String message) {
      
          Rectangle2D bounds = getBounds(message);
          return bounds.getWidth();
        }
      
        double getHeight(String message) {
      
          Rectangle2D bounds = getBounds(message);
          return bounds.getHeight();
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2015-07-31
        • 1970-01-01
        • 2013-10-17
        • 1970-01-01
        • 2019-04-08
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        • 1970-01-01
        相关资源
        最近更新 更多