java 如何限制 JTextArea 中的行数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12160060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Limit number of lines in JTextArea?
提问by Ralph Andreasen
I am trying to make a GUI for a service, which have a JTextArea to view messages in, each message is written on a single line, and wordwrapped if needed.
我正在尝试为服务制作一个 GUI,它有一个 JTextArea 来查看消息,每条消息都写在一行上,并在需要时进行自动换行。
The messages arrive via a socket, so it is merely an .append(message) that i am using to update the JTextArea, i need to limit these lines to 50 or 100 and i have no need to limit character count on each line.
消息通过套接字到达,因此它只是我用来更新 JTextArea 的 .append(message),我需要将这些行限制为 50 或 100,而且我不需要限制每一行的字符数。
If there is a method to limit the number lines in the JTextArea or if there is an alternative method of doing it?
如果有一种方法可以限制 JTextArea 中的数字行,或者是否有其他方法可以做到这一点?
I could really use the assistance in this matter.
我真的可以在这件事上使用帮助。
Edit
编辑
The problem is that each client can send infinite lines, all these lines have to be readable, so this is not a simple check of the number of lines in the JTextArea. I need to remove older lines in order to view newer lines.
问题是每个客户端都可以发送无限行,所有这些行都必须是可读的,所以这不是对 JTextArea 中行数的简单检查。我需要删除旧行才能查看新行。
采纳答案by yan bellavance
Would this be more efficient?
这会更有效率吗?
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();
}
}
}
回答by StanislavL
Use thisto get row and column
使用它来获取行和列
Add a DocumentFilter which checks amount of rows (pass the doc.getLength() offset) and prevent adding more text.
添加一个 DocumentFilter 来检查行数(传递 doc.getLength() 偏移量)并防止添加更多文本。
Or you can create a dummy invisible JTextArea and add all the text there. Then measure last allowed line and cut the text.
或者您可以创建一个虚拟的不可见 JTextArea 并在那里添加所有文本。然后测量最后允许的行并剪切文本。
回答by kleopatra
Below is a crude DocumentFilter which appears to work. Its basic approach is to let the insert/append happen, query the number of lines after the fact, if more the the max, remove lines from the start as appropriate.
下面是一个粗略的 DocumentFilter,它似乎可以工作。它的基本方法是让插入/追加发生,事后查询行数,如果超过最大值,则根据需要从开始处删除行。
Beware: the lines counted with the textArea methods are (most probably, waiting for confirmation from @Stani) lines-between-cr, not the actual lines as layouted. Depending on your exact requirement, they may or may not suite you (if not, use the Stan's utility methods)
请注意:使用 textArea 方法计算的行数(最有可能是等待@Stani 的确认)lines-between-cr,而不是实际布局的行。根据您的确切要求,它们可能适合您,也可能不适合您(如果不适合,请使用 Stan 的实用方法)
I was surprised and not entirely sure if it's safe
我很惊讶,并不确定它是否安全
- surprised: the insert method isn't called, needed to implement the replace method instead (in production ready code probably both)
- not sure if the textArea is guaranteed to return up-to-date values in the filter methods (probably not, then the length check can be wrapped in an invokeLater)
- 惊讶:插入方法没有被调用,需要实现替换方法(在生产就绪代码中可能两者都有)
- 不确定 textArea 是否保证在过滤器方法中返回最新值(可能不是,那么长度检查可以包含在 invokeLater 中)
Some code:
一些代码:
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));
回答by Thomas Adkins
My approach works with the content of the JTextPane as a document. It assumes that your program has been appending text to the end of the document over and over, so that when you call doc.getCharacterElement(1), you will get basically a leaf element that represents the earliest line of code. This is what we want to delete, so then we get the start and end offsets of that element, and call the remove method to cut the earliest text.
我的方法将 JTextPane 的内容作为文档使用。它假定您的程序已经一遍又一遍地将文本附加到文档的末尾,因此当您调用 doc.getCharacterElement(1) 时,您基本上将获得一个代表最早代码行的叶元素。这就是我们要删除的内容,于是我们得到那个元素的开始和结束偏移量,调用remove方法来剪切最早的文本。
This could be selectively performed by checking whether the number of characters total is greater than a million (as I have done below), or based on the number of lines you have already added.
这可以通过检查字符总数是否大于一百万(正如我在下面所做的那样)或根据您已经添加的行数来选择性地执行。
If you want to based it on the number of lines already added, you will need a field that gets incremented each time you print to the JTextPane, so that this code runs once every time you print a new line of text and the count exceeds your maximum value.
如果您想基于已添加的行数,您将需要一个每次打印到 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();
}
}
Cheers!
干杯!