3

I've used other excellent answers to design a method that returns the correct dimension of a JTextPane, given it's content and width, using LineBreakMeasurer.

The problem is that it is slightly of when I try different font sizes, and I can't figure out why. It works perfectly for say Arial 12 but not for Arial 8 or Arial 16 because then nextLayout calcuates the length wrong. Can anyone tell me why?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextLayout;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.border.LineBorder;


public class Example1 {

static JFrame frame = new JFrame();
static JPanel bigPanel = new JPanel();
static JTextPane textPane[] = new JTextPane[10];



public static void main(String[] args) {

    frame.setLayout(new FlowLayout());
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    for(int i=0 ; i<10 ; i++) {
        textPane[i] = new JTextPane();
        textPane[i].setFont(new Font("Arial", 0, 12+i ));
        textPane[i].setText("This is 10 characters of " + ((Integer)(10+i)).toString() + " points : a b c d e f g h i j");
        textPane[i].setPreferredSize(getTextDimension(textPane[i], 100));
        textPane[i].setBorder(new LineBorder(Color.BLACK));
        frame.add(textPane[i]);
    }

    frame.setSize(500, 500);
    frame.setVisible(true);

}

static private Dimension getTextDimension(JTextPane textPane, float width) {

    FontMetrics fm = textPane.getFontMetrics(textPane.getFont());
    int fontHeight = fm.getHeight()+ fm.getDescent();
    //int fontHeight = fm.getHeight();

    AttributedString text = new AttributedString(textPane.getText());
    FontRenderContext frc = textPane.getFontMetrics(textPane.getFont()).getFontRenderContext();
    AttributedCharacterIterator styledText = text.getIterator();
    LineBreakMeasurer measurer = new LineBreakMeasurer(styledText, frc);

    float wrappingWidth = width - textPane.getInsets().left - textPane.getInsets().right;

    int lines = 0;
     while (measurer.getPosition() < styledText.getEndIndex()) {
        TextLayout layout = measurer.nextLayout(wrappingWidth);
        lines++;
     }

     return new Dimension((int)Math.round(width), lines * fontHeight);
}

}

4

2 に答える 2