FontMetrics.getStringBounds for AttributedString gives wrong result?

前端 未结 2 1349
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-15 10:25

As shown in the following picture, an AttributedString is drawn on a JPanel (500X500).

The FontMetrics.getStringBounds() of that AttributedString gives a

相关标签:
2条回答
  • 2021-01-15 11:02

    The FontMetrics only receives a CharacterIterator, and does not take into account that it is actually an AttributedCharacterIterator. You can use a TextMeasurer to compute the actual bounds of your string. For comparison, add this after you called the drawString method:

        // Compensate for the 50,50 of the drawString position
        g.translate(50, 50);
    
        g.setColor(Color.RED);
        Rectangle2D wrongBounds = fm.getStringBounds(
                text.getIterator(), 0, text.getIterator().getEndIndex(), g);
        g.draw(wrongBounds);
        System.out.println("wrong: "+wrongBounds);
    
        g.setColor(Color.BLUE);
        AttributedCharacterIterator iterator = text.getIterator();
        TextMeasurer tm = new TextMeasurer(iterator, g.getFontRenderContext());
        Rectangle2D rightBounds = tm.getLayout(0, iterator.getEndIndex()).getBounds();
        g.draw(rightBounds);
        System.out.println("right: "+rightBounds);
    

    (And BTW: Don't call g.dispose() on the Graphics that was handed to you in the paintComponent method)

    0 讨论(0)
  • 2021-01-15 11:15

    FontMetrics fontMetrics = graphics.getFontMetrics() returns a FontMetrics object based on the single font currently set on the graphics object. You are not changing the font used by graphics explicitly so it uses the default font designated for JPanel by the current L&F.

    FontMetrics methods related to bounds calculation accept a "simple" CharacterIterator (which does not provide font information) instead of AttributedCharacterIterator (which does). Hence fontMetrics.getStringBounds() simply calculates the text bounds based on the single font of the same size.

    You need to use java.awt.font.TextLayout to determine the proper bounds when using AttributedCharacterIterator with different fonts and font sizes:

    TextLayout textLayout = new TextLayout( 
            text.getIterator(), 
            g.getFontRenderContext() 
    );
    Rectangle2D.Float textBounds = ( Rectangle2D.Float ) textLayout.getBounds();
    
    g.drawString( text.getIterator(), 50, 50 );
    // lets draw a bounding rect exactly around our text
    // to be sure we calculated it properly
    g.draw( new Rectangle2D.Float(
            50 + textBounds.x, 50 + textBounds.y,
            textBounds.width, textBounds.height
    ) );
    
    0 讨论(0)
提交回复
热议问题