如何限制JTextArea中的行数?

时间:2012-08-28 13:13:46

标签: java swing jtextarea

我正在尝试为服务创建一个GUI,它有一个JTextArea来查看消息,每条消息都写在一行上,并在需要时进行自动换行。

消息通过套接字到达,所以它只是我用来更新JTextArea的.append(消息),我需要将这些行限制为50或100,我不需要限制每个字符数线。

如果有一种方法来限制JTextArea中的数字行,或者是否有另一种方法可以做到这一点?

我真的可以在这件事上使用帮助。

修改

问题是每个客户端都可以发送无限行,所有这些行都必须是可读的,所以这不是对JTextArea中行数的简单检查。我需要删除较旧的行才能查看更新的行。

4 个答案:

答案 0 :(得分:6)

使用this获取行和列

添加一个DocumentFilter,用于检查行数(传递doc.getLength()偏移量)并阻止添加更多文本。

或者您可以创建一个虚拟的不可见JTextArea并在那里添加所有文本。然后测量最后允许的行并剪切文本。

答案 1 :(得分:6)

下面是一个粗糙的DocumentFilter,似乎可行。它的基本方法是让插入/追加发生,查询事后的行数,如果越多,则从适当的开始删除行。

注意:使用textArea方法计算的行(很可能是等待来自@Stani的确认)line-between-cr,而不是实际行的布局。根据您的具体要求,他们可能会或可能不会为您服务(如果没有,请使用Stan的实用方法)

我很惊讶,并不完全确定它是否安全

  • 很惊讶:没有调用insert方法,而是需要实现替换方法(在生产就绪代码中可能两者都有)
  • 不确定textArea是否保证在过滤器方法中返回最新值(可能不是,然后长度检查可以包装在invokeLater中)

一些代码:

public class MyDocumentFilter extends DocumentFilter {

    private JTextArea area;
    private int max;

    public MyDocumentFilter(JTextArea area, int max) {
        this.area = area;
        this.max = max;
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length,
            String text, AttributeSet attrs) throws BadLocationException {
        super.replace(fb, offset, length, text, attrs);
        int lines = area.getLineCount();
        if (lines > max) {
            int linesToRemove = lines - max -1;
            int lengthToRemove = area.getLineStartOffset(linesToRemove);
            remove(fb, 0, lengthToRemove);
        }
    }
}

// usage
JTextArea area = new JTextArea(10, 10);
((AbstractDocument) area.getDocument()).setDocumentFilter(new MyDocumentFilter(area, 3));

答案 2 :(得分:6)

这会更有效吗?

final int SCROLL_BUFFER_SIZE = 100;
public void trunkTextArea(JTextArea txtWin)
{
    int numLinesToTrunk = txtWin.getLineCount() - SCROLL_BUFFER_SIZE;
    if(numLinesToTrunk > 0)
    {
        try
        {
            int posOfLastLineToTrunk = txtWin.getLineEndOffset(numLinesToTrunk - 1);
            txtWin.replaceRange("",0,posOfLastLineToTrunk);
        }
        catch (BadLocationException ex) {
            ex.printStackTrace();
        }
    }
}

答案 3 :(得分:1)

我的方法使用JTextPane的内容作为文档。它假定您的程序一直在文档的末尾附加文本,因此当您调用doc.getCharacterElement(1)时,您将基本上获得表示最早代码行的叶元素。这是我们想要删除的内容,因此我们得到该元素的开始和结束偏移量,并调用remove方法来删除最早的文本。

这可以通过检查字符总数是否大于一百万(如下所述)或基于您已添加的行数来有选择地执行。

如果您希望将其基于已添加的行数,则每次打印到JTextPane时都需要一个递增的字段,以便每次打印新的文本行时此代码都会运行一次计数超过您的最大值。

        JTextPane pane = ...
        StyledDocument doc = pane.getStyledDocument();
        int size = doc.getLength();
        if (size > 1000000) {
            out.println("Size: " + size);
            out.println(":" + 1);
            int i = 0;
            Element e = doc.getCharacterElement(i + 1);
            int start = e.getStartOffset();
            int end = e.getEndOffset();

            try {
                doc.remove(start, end);
            } catch (BadLocationException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }

干杯!