【问题标题】:Java - Resizing font to fit areaJava - 调整字体大小以适应区域
【发布时间】:2016-10-06 04:23:42
【问题描述】:

多年来,我多次遇到过调整文本大小以适应 Java GUI 上某个区域的问题。我的解决方案通常是通过以下方式解决该问题:

  • 重新设计界面以避免问题

  • 更改区域以适合文本大小

  • 对正确大小的字体进行二分搜索以适合字符串(当我无法做到前两个时)

最近在处理另一个需要快速确定给定区域的正确字体大小的项目时,我的二进制搜索方法太慢了(我怀疑是因为按顺序多次创建和测量字体涉及动态内存分配) 并在我的应用程序中引入了明显的延迟。我需要的是一种更快更简单的方法来计算字体大小,从而允许渲染给定的字符串以适应 GUI 的定义区域。

【问题讨论】:

    标签: java fonts font-size


    【解决方案1】:

    最后我想到有一种更简单、更快捷的方法,只需要在运行时进行少量分配。这种新方法无需进行任何类型的搜索,并且只需要进行 1 次测量,但是,它确实需要做出一个假设,该假设对于大多数应用来说是完全合理的。

    • 字体的宽度和高度必须与字体的磅值成正比。除了对渲染上下文进行的最模糊的转换之外,所有其他转换都会发生这种情况。

    使用这个假设,我们可以计算字体尺寸与磅值的比率,并通过线性推断找到给定区域所需的字体大小。我为此编写的一些代码如下:

    编辑: 初始测量的准确性受基本字体大小的限制。使用非常小的字体大小作为基础可能会影响结果。但是基础字体越大越准确,线性逼近越准确。

    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Shape;
    import java.awt.font.GlyphVector;
    import java.awt.geom.Rectangle2D;
    
    public class FontUtilities
    {   
        public static Font createFontToFit
        (
            String value,
            double width,
            double height,
            Font base,
            Graphics context
        )
        {
            double measuredWidth;
            double measuredHeight;
            double baseFontSize;
            FontMetrics ruler;
            Rectangle2D bounds;
            double heightBasedFontSize;
            double widthBasedFontSize;
            GlyphVector vector;
            Shape outline;
    
            if
            (
                (value == null) ||
                (base == null) ||
                (context == null) ||
                (width != width) ||
                (height != height)
            )
            {
                return null;
            }
    
            //measure the size of the string in the current font size
            baseFontSize = base.getSize2D();
            ruler = context.getFontMetrics(base);
    
    
            vector = base.createGlyphVector(ruler.getFontRenderContext(), value);
    
            //use the bounds measurement on the outline of the text since this is the only
            //measurement method that seems to be bug free and consistent in java
            outline = vector.getOutline(0, 0);
            bounds = outline.getBounds();
    
            measuredWidth = bounds.getWidth();
            measuredHeight = bounds.getHeight();
    
            //assume that each of the width and the height of the string
            //is proportional to the font size, calculate the ratio
            //and extrapolate linearly to determine the needed font size.
            //should have 2 font sizes one for matching the width, and one for
            //matching the height, return the least of the 2
            widthBasedFontSize = (baseFontSize*width)/measuredWidth;
            heightBasedFontSize = (baseFontSize*height)/measuredHeight;
    
            if(widthBasedFontSize < heightBasedFontSize)
            {
                return base.deriveFont(base.getStyle(), (float)widthBasedFontSize);
            }
            else
            {
                return base.deriveFont(base.getStyle(), (float)heightBasedFontSize);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-31
      • 2011-05-23
      • 2016-12-19
      • 2013-06-04
      • 2016-11-27
      • 2015-12-10
      • 2018-04-21
      • 2012-08-10
      相关资源
      最近更新 更多