【问题标题】:How do you draw a string centered vertically in Java?如何在 Java 中绘制垂直居中的字符串?
【发布时间】:2015-09-01 03:22:12
【问题描述】:

我知道这是一个简单的概念,但我在字体指标方面遇到了困难。水平居中并不太难,但垂直居中似乎有点困难。

我尝试过以各种组合方式使用 FontMetrics getAscent、getLeading、getXXXX 方法,但无论我尝试什么,文本总是偏离几个像素。有没有办法测量文本的确切高度,使其完全居中。

【问题讨论】:

    标签: java graphics


    【解决方案1】:

    注意,您确实需要准确考虑垂直居中的含义。

    字体在基线上呈现,沿着文本底部延伸。垂直空间分配如下:

    ---
     ^
     |  leading
     |
     -- 
     ^              Y     Y
     |               Y   Y
     |                Y Y
     |  ascent         Y     y     y 
     |                 Y      y   y
     |                 Y       y y
     -- baseline ______Y________y_________
     |                         y                
     v  descent              yy
     --
    

    前导只是字体推荐的行间距。为了在两点之间垂直居中,您应该忽略前导(它是 ledding,顺便说一句,不是 leeding;在一般排版中,它是/曾经是印版中的行之间插入的引线间距)。

    因此,为了使文本上升和下降居中,您需要

    baseline=(top+((bottom+1-top)/2) - ((ascent + descent)/2) + ascent;
    

    没有最后的“+ ascent”,你就有了字体顶部的位置;因此添加上升是从顶部到基线。

    另外,请注意字体高度应该包括前导,但有些字体不包括它,并且由于舍入差异,字体高度可能不完全相等(前导 + 上升 + 下降)。

    【讨论】:

    • 哦,哇,这是一个完美的解释。非常感谢! (也是为了说明领先,不知道)
    • 加 1 的任何原因?
    • @Alex:因为 (bottom+1-top) 是高度;如果底部和顶部相同,则高度为一,而不是零。如果中点为 n.5 像素,则最终效果是向下舍入。
    【解决方案2】:

    我找到了一个食谱here

    关键方法似乎是getStringBounds()getAscent()

    // Find the size of string s in font f in the current Graphics context g.
    FontMetrics fm   = g.getFontMetrics(f);
    java.awt.geom.Rectangle2D rect = fm.getStringBounds(s, g);
    
    int textHeight = (int)(rect.getHeight()); 
    int textWidth  = (int)(rect.getWidth());
    int panelHeight= this.getHeight();
    int panelWidth = this.getWidth();
    
    // Center text horizontally and vertically
    int x = (panelWidth  - textWidth)  / 2;
    int y = (panelHeight - textHeight) / 2  + fm.getAscent();
    
    g.drawString(s, x, y);  // Draw the string.
    

    (注意:上面的代码被页面上的MIT License 覆盖。)

    【讨论】:

    • 是的...我很熟悉这个概念...但它是错误的。 fm.getAscent() 方法是问题所在。它不报告字体的实际像素上升,并导致文本更接近底部而不是顶部。
    【解决方案3】:

    不确定这是否有帮助,但drawString(s, x, y) 将文本的基线设置为 y。

    我正在做一些垂直居中的工作,直到我注意到文档中提到的行为之前,我无法让文本看起来正确。我假设字体的底部在 y 处。

    对我来说,解决方法是从 y 坐标中减去 fm.getDescent()

    【讨论】:

      【解决方案4】:

      另一个选项是来自TextLayout classgetBounds 方法。

      Font f;
      // code to create f
      String TITLE = "Text to center in a panel.";
      FontRenderContext context = g2.getFontRenderContext();
      
      TextLayout txt = new TextLayout(TITLE, f, context);
      Rectangle2D bounds = txt.getBounds();
      int xString = (int) ((getWidth() - bounds.getWidth()) / 2.0 );
      int yString = (int) ((getHeight() + bounds.getHeight()) / 2.0);
      // g2 is the graphics object 
      g2.setFont(f);
      g2.drawString(TITLE, xString, yString);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-25
        • 2011-05-25
        • 2017-10-04
        • 2019-03-09
        • 1970-01-01
        相关资源
        最近更新 更多