如何计算JTextArea中的行数,包括由包装引起的行数?

我有一个JTextArea,我已将word-wrap和wrap-style-word设置为true。 我希望将JTextArea“打包”到给定指定宽度的最小可能高度。

要做到这一点,我正在计划使用…计算字体的高度

Font font = jTextArea.getFont(); FontMetrics fontMetrics = jTextArea.getFontMetrics(font); int lineHeight = fontMetrics.getAscent() + fontMetrics.getDescent(); 

…然后将其乘以JTextArea中使用的行数。 问题是JTextArea.getLineCount()计算忽略换行的换行数。

如何计算JTextArea中使用的行数,包括由自动换行引起的行数?

这里有一些演示代码可以更轻松地解决这个问题。 我有一个监听器,每次调整窗口大小时都会打印出行数。 目前,它总是打印1,但我想补偿自动换行并打印出实际使用的行数。

编辑:我在下面的代码中包含了问题的解决方案。 静态countLines方法提供了解决方案。

 package components; import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.text.*; import javax.swing.*; public class JTextAreaLineCountDemo extends JPanel { JTextArea textArea; public JTextAreaLineCountDemo() { super(new GridBagLayout()); String inputStr = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo"; textArea = new JTextArea(inputStr); textArea.setEditable(false); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); // Add Components to this panel. GridBagConstraints c = new GridBagConstraints(); c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; c.weighty = 1.0; add(textArea, c); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent ce) { System.out.println("Line count: " + countLines(textArea)); } }); } private static int countLines(JTextArea textArea) { AttributedString text = new AttributedString(textArea.getText()); FontRenderContext frc = textArea.getFontMetrics(textArea.getFont()) .getFontRenderContext(); AttributedCharacterIterator charIt = text.getIterator(); LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc); float formatWidth = (float) textArea.getSize().width; lineMeasurer.setPosition(charIt.getBeginIndex()); int noLines = 0; while (lineMeasurer.getPosition() < charIt.getEndIndex()) { lineMeasurer.nextLayout(formatWidth); noLines++; } return noLines; } private static void createAndShowGUI() { JFrame frame = new JFrame("JTextAreaLineCountDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JTextAreaLineCountDemo()); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } 

您可以使用LineBreakMeasurer类。

LineBreakMeasurer类允许将样式文本分解为适合特定视觉前进的线条(或线段)。 这对于希望显示适合特定宽度的文本段落的客户端非常有用,称为包装宽度.LineBreakMeasurer实现了最常用的换行策略:适合包装宽度的每个单词都放在行上。 如果第一个单词不适合,那么适合包装宽度的所有字符都放在该行上。 每行至少放置一个字符。

在我看来,这不可能是所有答案。 如果更改字体并扩展文本,则linecount变得不正确。

编辑:解决方案 您必须设置textarea和属性字符串的字体。 现在linecount是正确的。 Code中的解决方案。

 package lineBreak; import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.text.*; import javax.swing.*; public class JTextAreaLineCountDemo extends JPanel { JTextArea textArea; static Font f = new Font("Helvetiva", Font.ITALIC, 50); public JTextAreaLineCountDemo() { super(new GridBagLayout()); String inputStr = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo, Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo, Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo, Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo"; textArea = new JTextArea(inputStr); textArea.setEditable(false); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); // Add Components to this panel. GridBagConstraints c = new GridBagConstraints(); c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; c.weighty = 1.0; add(textArea, c); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent ce) { **textArea.setFont(new Font("Arial", Font.BOLD, 22));** System.out.println("Line count: " + countLines(textArea)); } }); } private static int countLines(JTextArea textArea) { AttributedString text = new AttributedString(textArea.getText()); text.addAttribute(TextAttribute.FONT, f); FontRenderContext frc = textArea.getFontMetrics(textArea.getFont()) .getFontRenderContext(); AttributedCharacterIterator charIt = text.getIterator(); LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc); float formatWidth = (float) textArea.getSize().width; lineMeasurer.setPosition(charIt.getBeginIndex()); int noLines = 0; while (lineMeasurer.getPosition() < charIt.getEndIndex()) { lineMeasurer.nextLayout(formatWidth); noLines++; } return noLines; } private static void createAndShowGUI() { JFrame frame = new JFrame("JTextAreaLineCountDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JTextAreaLineCountDemo()); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } 

你的countLines方法几乎对我countLines ,但我必须做一些调整才能使它在我的情况下正常工作。 我假设您使用的是默认字体并且JTextArea上没有边框,但是使用非默认字体或具有边框(或两者都是如此)将导致您的countLines方法返回错误的数字。 下面是我更新的版本,它考虑了这两个因素(并且还使用textArea.getWidth()而不是textArea.getSize().width )。

 private static int countLines(JTextArea textArea) { AttributedString text = new AttributedString(textArea.getText()); text.addAttribute(TextAttribute.FONT, textArea.getFont()); FontRenderContext frc = textArea.getFontMetrics(textArea.getFont()).getFontRenderContext(); AttributedCharacterIterator charIt = text.getIterator(); LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc); Insets textAreaInsets = textArea.getInsets(); float formatWidth = textArea.getWidth() - textAreaInsets.left - textAreaInsets.right; lineMeasurer.setPosition(charIt.getBeginIndex()); int noLines = 0; while (lineMeasurer.getPosition() < charIt.getEndIndex()) { lineMeasurer.nextLayout(formatWidth); noLines++; } return noLines; } 

认识到AttributedString需要将其字体设置为JTextArea字体的所有功劳都归功于Jenny