Java(AWT):将文本适合框中

3

我有一个扩展了Frame的应用程序。然后,它将使用以下方式显示几行文本:

Font f = new Font("Arial", Font.PLAIN, 10);
g.setFont(f);
g.drawString("Test|great Yes ^.", x, y + 10);

现在的情况是文本不适合框内。例如,我期望文本适合[x,y]-[x+width, y+10](不关心宽度),但它会略微下降到y+10线以下。对于大多数字符('T','e'等),这是适合的,但'|'和'g'不是!它们会落到y+10线以下。似乎你不能使用:draw at y + characterHeight。但是什么有效呢?
为了理解我的意思,这里有一些样例代码:
import java.awt.*;

public class test extends Frame
{
        public test()
        {
                /* retrieve max window size */
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice[] gs = ge.getScreenDevices();
                GraphicsConfiguration [] gc = gs[0].getConfigurations();
                Rectangle r = gc[0].getBounds();
                setSize(r.width, r.height);
                setVisible(true);
        }

        public void paint(Graphics g)
        {
                final int windowWidth  = getSize().width;
                final int windowHeight = getSize().height;
                g.setColor(Color.BLUE);
                g.fillRect(0, 0, windowWidth, windowHeight);
                g.setColor(Color.WHITE);
                g.fillRect(0, 100, windowWidth, 110);
                int textHeight = 100;
                Font f = new Font("Arial", Font.PLAIN, textHeight);
                g.setFont(f);
                g.setColor(Color.BLACK);
                g.drawString("Test|great Yes ^.", 10, 100 + textHeight);
        }

        public void guiLoop()
        {
                for(;;) { try { Thread.sleep(1000); } catch(Exception e) { } }
        }

        public static void main(String [] args)
        {
                new test().guiLoop();
        }
}

我也尝试了以下代码:
public void paint(Graphics g)
{
        final int windowWidth  = getSize().width;
        final int windowHeight = getSize().height;
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, windowWidth, windowHeight);
        g.setColor(Color.WHITE);
        g.fillRect(0, 100, windowWidth, 110);
        int textHeight = 100;

        String str = "Test|great Yes ^.";
        Font f = new Font("Arial", Font.PLAIN, textHeight);
        Rectangle2D boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
        f = f.deriveFont((float)(textHeight * (textHeight / boundingRectangle.getHeight())));
        boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
        g.drawString(str, 10, 100 + (int)boundingRectangle.getHeight());

        g.setFont(f);
        g.setColor(Color.BLACK);
        g.drawString(str, 10, 100 + textHeight);
}

这有所改善: 文字变小了,所以可能适合,但问题仍然存在,y轴位置不正确。
感谢您的所有帮助!

guiLoop() 真的必要吗? - Suppressingfire
2个回答

4
使用FontMetrics怎么样?您可以从Graphics对象中使用g.getFontMetrics()获取它。
然后,您可以检索最大下降或上升或直接高度(使用getHeight),因此您的实现将是与字体无关的,并且应该可以正常工作。请在此处查看文档!
编辑(解释评论):没有一种直接的方法告诉字符串以适合框的方式绘制自己。您必须自己做...例如从最大字体大小开始,检查宽度是否适合框,否则减小大小并再次尝试。对于高度,您应该首先决定(或获得)最大字体高度,然后可以设置框应该有多少像素。

是的,特别是FontMetrics.stringWidth():http://java.sun.com/j2se/1.5.0/docs/api/java/awt/FontMetrics.html#stringWidth%28java.lang.String%29 - Suppressingfire
是的,但是如何处理这些指标呢?我尝试在 y + fontmetrics.getAscent() 处绘制字符串,但这也会将文本绘制得太低。 - Folkert van Heusden
2
另一个问题是这些方法告诉您文本将变得多大:难道我不能说这个字符串s必须适合这个边界框吗? - Folkert van Heusden
我认为stringWidth不适用于此情况,因为我们讨论的是高度。你应该使用getHeight,正如文档所述:“获取此字体中一行文本的标准高度。这是相邻文本行基线之间的距离。它是前导+上升+下降的总和。”你不能限制字符串,那么它应该怎么做?自动调整大小吗? - Jack

0

我认为我有点解决了它:

boundingBoxHeight:文本应适合的框的高度 yOffset:从哪里开始绘制字体

            Font f = new Font("Arial", Font.PLAIN, boundingBoxHeight);
            g.setFont(f);
            FontMetrics fm = g.getFontMetrics();
            double shrink = ((double)textHeight / (double)fm.getHeight());
            double newSize = (double)textHeight * shrink;
            double newAsc  = (double)fm.getAscent() * shrink;
            int yOffset = (int)newAsc - fm.getLeading();
            f = f.deriveFont((float)newSize);
            g.setFont(f);

            g.drawString(str, 10, 100 + yOffset);

不过,文本上方有相当多的空白。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接