gpt4 book ai didi

java - 如何计算文本在 JTextArea 中的行数(以及每行中的列数)?

转载 作者:搜寻专家 更新时间:2023-10-30 21:00:10 27 4
gpt4 key购买 nike

在对 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]

在我的脑海中编译你们所有人所说的我认为可能可靠的解决方案可能是破解文本区域设置文本的方式,并采取完整控制它。通过运行算法(上面一个,请注意,正如@trashgod 所建议的那样,该区域的 setText 中的“<”已更改为“<=”)。

是什么让我这样想的......例如在我提供的示例中,如果你将 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);
}
});
}
}

提前致谢。

最佳答案

What am I doing wrong, what am I forgetting about?

没什么,真的。我修改了您的示例以在宽度上使用“<=”并突出显示一些功能:

  1. FontMetrics注意,“String 的进步不一定是孤立测量的其字符进步的总和……”

  2. 文本组件的首选大小与最宽行的度量边界非常匹配。由于比例间距,这因字体而异。

  3. TextLayout显示更严格的界限,但请注意“基线相对坐标”。

  4. getLineCount() 方法计算 line.separator 分隔线,而不是换行。

line: Twas brillig and the slithy tovesline: Did gyre and gimble in the wabe;line count: 2preferred: java.awt.Dimension[width=207,height=48]bounds1: java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.568359,w=205.0,h=15.310547]layout1: java.awt.geom.Rectangle2D$Float[x=0.0,y=-10.0,w=200.0,h=13.0]bounds2: java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.568359,w=207.0,h=15.310547]layout2: java.awt.geom.Rectangle2D$Float[x=1.0,y=-10.0,w=205.0,h=13.0]
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

/** #see http://stackoverflow.com/questions/5979795 */
public class TextAreaLine {

private static final String text1 =
"Twas brillig and the slithy toves\n";
private static final String text2 =
"Did gyre and gimble in the wabe;";
private static final JTextArea ta = new JTextArea(text1 + text2);

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
display();
}
});
}

static void display() {
JFrame f = new JFrame();
ta.setWrapStyleWord(false);
ta.setLineWrap(false);
ta.setRows(3);
f.add(ta);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setVisible(true);
FontMetrics fm = ta.getFontMetrics(ta.getFont());
List<String> texts = new ArrayList<String>();
Dimension d = ta.getPreferredSize();
String text = ta.getText();
String line = "";
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c != '\n') {
if (fm.stringWidth(line + c) <= d.width) {
line += c;
} else {
texts.add(line);
line = "" + c;
}
}
}
texts.add(line);
for (String s : texts) {
System.out.println("line: " + s);
}
System.out.println("line count: " + ta.getLineCount());
System.out.println("preferred: " + d);
System.out.println("bounds1: " + fm.getStringBounds(text1, null));
FontRenderContext frc = new FontRenderContext(null, false, false);
TextLayout layout = new TextLayout(text1, ta.getFont(), frc);
System.out.println("layout1: " + layout.getBounds());
System.out.println("bounds2: " + fm.getStringBounds(text2, null));
layout = new TextLayout(text2, ta.getFont(), frc);
System.out.println("layout2: " + layout.getBounds());
}
}

关于java - 如何计算文本在 JTextArea 中的行数(以及每行中的列数)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5979795/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com