¿Cómo calcular el número de filas (y columnas en cada fila) que toma un texto en un JTextArea?

Después de interesarse por el problema presentado en lapregunt Traté de abordarlo varias veces y fallé, y no me gusta eso:)

Creo que si el problema se dividiera en problemas secundarios, podría ayudar a resolverlo.

Para simplificar, supongamos que JTextArea no cambiará su tamaño, por lo que no debemos preocuparnos por la reevaluación, etc. Creo que los problemas importantes son:

1.¿Cómo calcular el número de filas que toma un determinado texto en un JTextArea?

2. ¿Cuál es la relación entre el número de columnas en un JTextArea y un número de caracteres que puede caber en una fila? Entonces podemos calcular la longitud de la fila.

Por favor, encuentre a continuación el código de muestra que presenta el área de texto para procesar:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class TextAreaLines
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JPanel p = new JPanel();
                JFrame f = new JFrame();
                JTextArea ta = new JTextArea("dadsad sasdasdasdasdasd");
                ta.setWrapStyleWord(true);
                ta.setLineWrap(true);
                ta.setRows(5);
                ta.setColumns(5);
                p.add(ta);
                f.setContentPane(p);
                f.setSize(400, 300);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);             
                //BTW the code below prints 1
                System.out.println("ta.getLineCount()="+ta.getLineCount());
            }
        });
    }
}

EDIT1: Así que se me ocurrió el siguiente código, pero el problema es que la salida no es lo que ves, es decir,

//for input
//JTextArea ta = new JTextArea("alfred abcdefghijklmnoprstuwvxyz abcdefg");

//we have output    
//s=alfred abcdefghijk
//s=lmnoprstuwvxyz a
//s=bcdefg



        FontMetrics fm = ta.getFontMetrics(ta.getFont());
        String text = ta.getText();
        List<String> texts = new ArrayList<String>();               
        String line = "";
        //no word wrap
        for(int i = 0;i < text.length(); i++)  
        {       
            char c = text.charAt(i);
            if(fm.stringWidth(line +c)  <= ta.getPreferredSize().width)
            {                       
                //System.out.println("in; line+c ="+(line + c));
                line += c;
            }
            else
            {
                texts.add(line);//store the text
                line = ""+c;//empty the line, add the last char
            }
        }
        texts.add(line);                
        for(String s: texts)
            System.out.println("s="+s);

¿Qué estoy haciendo mal? ¿De qué me estoy olvidando? No hay ajuste de palabra en el área de texto.

EDIT2: @trashgod Esta es la salida que estoy obteniendo. Aparentemente de esto es que tenemos diferentes fuentes predeterminadas. Y el problema, de hecho, puede ser fuente o incluso dependiente del sistema. (PD: estoy en Win7).

line: Twas brillig and the slithy tovesD
line: id gyre and gimble in the wabe;
line count: 2
preferred: java.awt.Dimension[width=179,height=48]
bounds1: java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.064453,w=170.0,h=15.09375]
layout1: java.awt.geom.Rectangle2D$Float[x=0.28125,y=-8.59375,w=168.25,h=11.125]
bounds2: java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.064453,w=179.0,h=15.09375]
layout2: java.awt.geom.Rectangle2D$Float[x=0.921875,y=-8.59375,w=177.34375,h=11.125]

ompilando en mi cabeza lo que todos ustedes están diciendo, creo que elna solución posiblemente confiable podría ser hackear la forma en que el área de texto establece su texto y toma un control total sobre él. Al ejecutar el algoritmo (arriba de uno, tenga en cuenta que, según lo sugerido por @trashgod, '<' se cambió a '<=') en el setText del área.

Qué me hizo pensar así ... por ejemplo en la muestra que proporcioné si cambia el texto del área de texto aJTextArea ta = new JTextArea("alfred abcdefghijkl\nmnoprstuwvxyz ab\ncdefg"); como se calcula en mi caso, entonces encajará perfectamente en el área de texto.

EDIT3: Este es un tipo de solución que pirateé rápidamente, al menos ahora los caracteres mostrados y calculados son exactamente los mismos. ¿Alguien más puede echarle un vistazo y decirme, posiblemente, cómo funciona en otra máquina que no sea Win7? El siguiente ejemplo está listo para usar. Debería poder cambiar el tamaño de la ventana y obtener la impresión de líneas de la misma manera que ve.

import java.awt.BorderLayout;
import java.awt.FontMetrics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class TextAreaLines
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JPanel p = new JPanel(new BorderLayout());
                JFrame f = new JFrame();
                final JTextArea ta = new JTextArea("alfred abcdefghijklmnoprstuwvxyz abcdefg");
                ta.addComponentListener(new ComponentAdapter()
                {
                    @Override
                    public void componentResized(ComponentEvent e)
                    {
                        super.componentResized(e);
                        System.out.println("ta componentResized");
                        reformatTextAreaText(ta);
                    }
                });
                //ta.setWrapStyleWord(true);
                ta.setLineWrap(true);
                p.add(ta);
                f.setContentPane(p);
                f.setSize(200, 100);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }

            private void reformatTextAreaText(JTextArea ta)
            {
                String text = ta.getText();
                //remove all new line characters since we want to control line braking
                text = text.replaceAll("\n", "");
                FontMetrics fm = ta.getFontMetrics(ta.getFont());
                List<String> texts = new ArrayList<String>();
                String line = "";
                //no word wrap
                for(int i = 0; i < text.length(); i++)
                {
                    char c = text.charAt(i);
                    if(fm.stringWidth(line + c) <= ta.getPreferredSize().width)
                    {
                        //System.out.println("in; line+c ="+(line + c));
                        line += c;
                    }
                    else
                    {
                        texts.add(line);//store the text
                        line = "" + c;//empty the line, add the last char
                    }
                }
                texts.add(line);
     ,           //print out of the lines
                for(String s : texts)
                    System.out.println("s=" + s);
                //build newText for the
                String newText = "";
                for(String s : texts)
                    newText += s + "\n";
                ta.setText(newText);
            }
        });
    }
}

Gracias por adelantado

Respuestas a la pregunta(7)

Su respuesta a la pregunta