【发布时间】:2011-08-24 04:49:22
【问题描述】:
对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: 所以我想出了以下代码,但问题是输出不是你看到的,即
//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]
在我的脑海中编译你们所有人所说的话,我认为可能可靠的解决方案可能是破解文本区域设置其文本的方式,并采取完整的控制它。通过运行该区域的 setText 中的算法(请注意,如@trashgod 所建议的,上述算法将“
是什么让我有这样的想法……例如,如果您在我提供的示例中
将 textarea 的文本更改为 JTextArea ta = new JTextArea("alfred abcdefghijkl\nmnoprstuwvxyz ab\ncdefg");,因为它是在我的情况下计算的,那么它将完全适合 textarea。
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);
}
});
}
}
提前致谢。
【问题讨论】:
-
我在 C# 中做了这个[或类似的东西]...花了一些时间。我看看能不能把代码挖出来。
-
@Doug Chamberlain 非常欢迎所有的意见。希望你能找到它,Java实现中的问题将是相似的:)
-
@camickr @jjnguy @Aleadam @Doug Chamberlain 伙计们请查看我的编辑。我正在等待您的建议
-
感谢所有相关人员。所有答案都非常有帮助,尽管我只能接受一个。我选择了@trashgod,因为它对我最有用,因为它为我提供了通往我想出的“黑客”解决方案的方法。再次感谢。