如何从JTextArea中提取包含给定字体的文本的单词和换行信息

时间:2012-06-01 23:27:40

标签: java swing svg word-wrap jtextarea

我必须将样式文本转换为包装的简单文本(用于SVG自动换行)。我无法相信,JTextArea无法提取包装信息(包含多少行,哪些是换行符)。所以我创建了一个小框架程序:

package bla;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JTextArea;

public class Example1 extends WindowAdapter {
    private static String content = "01234567890123456789\n" + "0123456 0123456 01234567 01234567";
    JTextArea text;

    public Example1() {
        Frame f = new Frame("TextArea Example");
        f.setLayout(new BorderLayout());
        Font font = new Font("Serif", Font.ITALIC, 20);
        text = new JTextArea();
        text.setFont(font);
        text.setForeground(Color.blue);
        text.setLineWrap(true);
        text.setWrapStyleWord(true);
        f.add(text, BorderLayout.CENTER);
        text.setText(content);
        // Listen for the user to click the frame's close box
        f.addWindowListener(this);
        f.setSize(100, 511);
        f.show();
    }

    public static List<String> getLines( JTextArea text ) {
        //WHAT SHOULD I WRITE HERE
        return new ArrayList<String>();
    }

    public void windowClosing(WindowEvent evt) {
        List<String> lines = getLines(text);
        System.out.println( "Number of lines:" + lines.size());
        for (String line : lines) {
            System.out.println( line );
        }
        System.exit(0);
    }

    public static void main(String[] args) {
        Example1 instance = new Example1();
    }

}

如果你运行它,你会看到:

The displayed picture is this

我期望输出:

Number of lines:6
0123456789
0123456789
0123456
0123456
01234567
01234567

我应该写什么来代替评论?

完整答案:

那么,基于接受的答案的完整解决方案实际上没有显示框架(注意,你应该从结果中删除实际的换行符):

package bla;

import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;

public class Example1 {
    private static String content = "01234567890123456789\n" + "0123456 0123456 01234567 01234567";

    public static List<String> getLines( String textContent, int width, Font font ) throws BadLocationException {
        JTextArea text;
        text = new JTextArea();
        text.setFont(font);
        text.setForeground(Color.blue);
        text.setLineWrap(true);
        text.setWrapStyleWord(true);
        text.setText(content);
        text.setSize(width, 1);
        int lastIndex = 0;
        int index = Utilities.getRowEnd(text, 0);
        List<String> result = new ArrayList<String>();
        do {
            result.add( textContent.substring( lastIndex, Math.min( index+1, textContent.length() ) ) );
            lastIndex = index + 1;
        }
        while ( lastIndex < textContent.length() && ( index = Utilities.getRowEnd(text, lastIndex) ) > 0 );
        return result;
    }

    public static void main(String[] args) throws BadLocationException {
        Font font = new Font("Serif", Font.ITALIC, 20);
        Example1 instance = new Example1();
        for (String line : getLines(content,110,font)) {
            System.out.println( line.replaceAll( "\n", "") );
        }
    }

} 

在我身上打开问题(不是那么重要),为什么宽度为100px且包含jtextarea的框架比没有框架的jtextarea包含文本的宽度相同。这个想法?

3 个答案:

答案 0 :(得分:3)

JTextArea不支持样式文本,但它确实支持对其模型PlainDocument的面向行的访问,如下所示。供参考,

  • 不要不必要地混用AWT(Frame)和Swing(JTextArea)组件。
  • 应在event dispatch thread上构建和操作的Swing GUI对象。
  • 如上所述heregetLineCount()方法计算line.separator分隔线,而非包裹线。
  • BasicTextUI处理Look&amp;感觉依赖渲染;方法viewToModel()viewToModel()在两个坐标系之间进行转换。

控制台:

01234567890123456789
0123456 0123456
01234567 01234567

代码:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class Example2 {

    private static final Character SEP = Character.LINE_SEPARATOR;
    private static String content = ""
        + "01234567890123456789" + SEP
        + "0123456 0123456" + SEP
        + "01234567 01234567";
    private JTextArea text;

    public Example2() {
        JFrame f = new JFrame("TextArea Example");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Font font = new Font("Serif", Font.ITALIC, 20);
        text = new JTextArea(4, 8);
        text.setFont(font);
        text.setForeground(Color.blue);
        text.setLineWrap(true);
        text.setWrapStyleWord(true);
        text.setText(content);
        f.add(new JScrollPane(text));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        for (String s : getLines(text)) {
            System.out.println(s);
        }
    }

    private List<String> getLines(JTextArea text) {
        PlainDocument doc = (PlainDocument) text.getDocument();
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < text.getLineCount(); i++) {
            try {
                int start = text.getLineStartOffset(i);
                int length = text.getLineEndOffset(i) - start;
                list.add(doc.getText(start, length));
            } catch (BadLocationException ex) {
                ex.printStackTrace(System.err);
            }
        }
        return list;
    }

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

            @Override
            public void run() {
                Example2 instance = new Example2();
            }
        });
    }
}

答案 1 :(得分:2)

JTextArea确实有:getLines() method,这不适合你吗?

答案 2 :(得分:2)

使用Utilities.getRowEnd() 将0作为起始偏移,然后将前一行的结束偏移+1