多年来,我多次面对调整文本大小以适合Java GUI特定区域的问题。我的解决方案通常是通过以下方法解决此问题:


重新设计界面以避免出现问题
更改区域以适合文本大小
进行二进制搜索以找到适合字串的正确大小的字体(当我无法使用前两个字体时)


最近在进行另一个需要快速确定给定区域的正确字体大小的项目时,我的二进制搜索方法太慢了(我怀疑是因为动态内存分配涉及到多次按顺序创建和测量字体),并引入了我的申请明显滞后。我需要的是一种更快,更简单的方法来计算字体大小,该字体大小将允许呈现给定的字符串以适合GUI的定义区域。

最佳答案

最终我想到,有一种更简便,更快捷的方法,在运行时只需要少量分配即可。这种新方法消除了对任何类型搜索的需要,并且只需要进行一次测量,但是它确实需要做出一个假设,该假设对于大多数应用而言都是完全合理的。


字体的宽度和高度必须与字体的磅值成正比。除了对渲染上下文所做的最晦涩的转换之外,这种情况都会发生。


使用此假设,我们可以计算字体尺寸与点大小的比率,然后线性外推以找到给定区域所需的字体大小。我为此编写的一些代码如下:

编辑:
初始测量的精度受基本字体大小的限制。使用非常小的字体大小作为基数可能会导致结果失败。但是,基本字体的大小越大,线性近似值越准确。

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);
        }
    }
}

关于java - Java-调整字体大小以适合区域,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37659493/

10-11 22:21
查看更多