После того, как вы заинтересовались проблемой, представленной в question Я пытался подойти к нему несколько раз и потерпел неудачу, и мне это не нравится:)
Я думаю, что если бы проблема была разделена на вспомогательные вопросы, это могло бы помочь ее решить.
Для простоты предположим, что JTextArea не изменит свой размер, поэтому нам не нужно беспокоиться о переоценке и т.д. Я думаю, что важными проблемами являются:
1.Как рассчитать количество строк, которые имеет определенный текст в JTextArea?
2. Какова связь между количеством столбцов в JTextArea и количеством символов, которые он может вписать в строку? Таким образом, мы можем рассчитать длину строки.
Пожалуйста, найдите ниже пример кода, представляющего текстовую область для обработки:
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: Итак, я придумал следующий код, но проблема в том, что результат не тот, который вы видите, i.e
//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);
Что я делаю неправильно, о чем я забываю? В текстовой области нет обертывания слов.
EDIT2: @trashgod Это результат, который я получаю. Судя по всему, у нас есть разные шрифты по умолчанию. И проблема на самом деле может быть либо шрифтом, либо даже зависящим от системы. (PS: Я на 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]
Компиляция в моей голове, что все вы, ребята, говорите, я думаю, что возможно надежное решение может заключаться в том, чтобы взломать способ, которым текстовая область устанавливает свой текст, и полностью контролировать его, Запустив алгоритм (выше одного, пожалуйста, обратите внимание, как было предложено @trashgod, "<" было изменено на "< =" ) в setText области.
Что заставило меня так думать... например, в примере, который я представил, если вы
измените текст текстового поля на JTextArea ta = new JTextArea("alfred abcdefghijkl\nmnoprstuwvxyz ab\ncdefg");
, как он рассчитан в моем случае, тогда он отлично впишется в текстовое поле.
EDIT3: Это своего рода решение, которое я быстро взломал, по крайней мере, теперь показанные символы и рассчитанные точно совпадают. Может кто-то еще, пожалуйста, проверьте это и сообщите мне, возможно, как это работает на другой машине, а затем в Win7? Пример ниже готов к использованию, вы должны изменить размер окна и получить распечатку строк так же, как вы видите.
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);
}
});
}
}
Спасибо заранее.