java 如何限制 JTextArea 的最大行数和列数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/479182/
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 JTextArea max Rows and Columns?
提问by Billbo bug
I am using JTextArea in JScrollPane
我在 JScrollPane 中使用 JTextArea
I want to limit the maximum number of lines possible and the maximum chars in each line.
我想限制可能的最大行数和每行中的最大字符数。
I need that the string will be exactly like on the screen, each line will end with '\n' (if there another line after it) and the user will be able to insert only X lines and Y chars in each line.
我需要字符串与屏幕上的完全一样,每一行都以 '\n' 结尾(如果后面还有另一行),并且用户将只能在每行中插入 X 行和 Y 字符。
I tried to limit the lines but I don't know exactly how many lines do I have because of the line wrapping, The line wrapping is starting new line visually on the screen(because of the width of the JTextArea) but in the string of the component it is really the same line with no '\n' to indicate new line. I do not have an idea how to limit the max chars in each line while typing.
我试图限制行,但由于换行,我不知道到底有多少行,换行是在屏幕上视觉上开始新行(因为 JTextArea 的宽度),但在字符串中组件实际上是同一行,没有 '\n' 表示新行。我不知道如何在打字时限制每行中的最大字符数。
There are 2 stages:
有2个阶段:
- The typing of the string- keep that the user will not be able to type more then X lines and Y chars in each line. (even if the line wrap only visualy or the user typed '/n')
- Insert the string to the DB- after cliking 'OK' convert the string that every line will end with "/n" even if the user did not typed it and the line was wrapped only visualy.
- 字符串的输入 - 保持用户将无法在每行中输入超过 X 行和 Y 个字符。(即使换行仅可视化或用户输入了“/n”)
- 将字符串插入到 DB- 单击“确定”后,即使用户没有输入它并且该行仅在视觉上被换行,也可以转换每行将以“/n”结尾的字符串。
There are few problems if i will count the chars in the line and insert '/n' in the end of the line, thats why i decided to do it in two stages. In the first stage ehile the user is typing i would rather only limit it visualy and force line wrpping or something similar. Only in the second stage when i save string i will add the '/n' even if the user did not typed it in the end of the lines!
如果我计算行中的字符数并在行尾插入 '/n' 几乎没有问题,这就是我决定分两个阶段进行的原因。在第一阶段 ehile 用户输入我宁愿只限制它的视觉和强制换行或类似的东西。只有在第二阶段,当我保存字符串时,我才会添加 '/n',即使用户没有在行尾输入它!
Does anyone have an idea?
有没有人有想法?
I know that i will have to use DocumentFilter OR StyledDocument.
我知道我将不得不使用 DocumentFilter 或 StyledDocument。
Here is sample code that limit only the lines to 3:(but not the chars in row to 19)
这是仅将行限制为 3 的示例代码:(但不将行中的字符限制为 19)
private JTextArea textArea ;
textArea = new JTextArea(3,19);
textArea .setLineWrap(true);
textArea .setDocument(new LimitedStyledDocument(3));
JScrollPane scrollPane = new JScrollPane(textArea
public class LimitedStyledDocument extends DefaultStyledDocument
/** Field maxCharacters */
int maxLines;
public LimitedStyledDocument(int maxLines) {
maxCharacters = maxLines;
}
public void insertString(int offs, String str, AttributeSet attribute) throws BadLocationException {
Element root = this.getDefaultRootElement();
int lineCount = getLineCount(str);
if (lineCount + root.getElementCount() <= maxLines){
super.insertString(offs, str, attribute);
}
else {
Toolkit.getDefaultToolkit().beep();
}
}
/**
* get Line Count
*
* @param str
* @return the count of '\n' in the String
*/
private int getLineCount(String str){
String tempStr = new String(str);
int index;
int lineCount = 0;
while (tempStr.length() > 0){
index = tempStr.indexOf("\n");
if(index != -1){
lineCount++;
tempStr = tempStr.substring(index+1);
}
else{
break;
}
}
return lineCount;
}
}
回答by Nick Holt
The following worked for me:
以下对我有用:
public class LimitedLinesDocument extends DefaultStyledDocument
{
private static final String EOL = "\n";
private int maxLines;
public LimitedLinesDocument(int maxLines)
{
this.maxLines = maxLines;
}
public void insertString(int offs, String str, AttributeSet attribute) throws BadLocationException
{
if (!EOL.equals(str) || StringUtils.occurs(getText(0, getLength()), EOL) < maxLines - 1)
{
super.insertString(offs, str, attribute);
}
}
}
Where the StringUtils.occursmethod is as follows:
其中StringUtils.occurs方法如下:
public static int occurs(String str, String subStr)
{
int occurrences = 0;
int fromIndex = 0;
while (fromIndex > -1)
{
fromIndex = str.indexOf(subStr, occurrences == 0 ? fromIndex : fromIndex + subStr.length());
if (fromIndex > -1)
{
occurrences++;
}
}
return occurrences;
}
回答by Frederic Morin
Here's my version, based on Nick Holt's version.
这是我的版本,基于 Nick Holt 的版本。
Just for the records, this will be used in a prototype and has not been tested much (if at all).
只是为了记录,这将用于原型并且还没有经过太多测试(如果有的话)。
public class LimitedLinesDocument extends DefaultStyledDocument {
private static final long serialVersionUID = 1L;
private static final String EOL = "\n";
private final int maxLines;
private final int maxChars;
public LimitedLinesDocument(int maxLines, int maxChars) {
this.maxLines = maxLines;
this.maxChars = maxChars;
}
@Override
public void insertString(int offs, String str, AttributeSet attribute) throws BadLocationException {
boolean ok = true;
String currentText = getText(0, getLength());
// check max lines
if (str.contains(EOL)) {
if (occurs(currentText, EOL) >= maxLines - 1) {
ok = false;
}
} else {
// check max chars
String[] lines = currentText.split("\n");
int lineBeginPos = 0;
for (int lineNum = 0; lineNum < lines.length; lineNum++) {
int lineLength = lines[lineNum].length();
int lineEndPos = lineBeginPos + lineLength;
System.out.println(lineBeginPos + " " + lineEndPos + " " + lineLength + " " + offs);
if (lineBeginPos <= offs && offs <= lineEndPos) {
System.out.println("Found line");
if (lineLength + 1 > maxChars) {
ok = false;
break;
}
}
lineBeginPos = lineEndPos;
lineBeginPos++; // for \n
}
}
if (ok)
super.insertString(offs, str, attribute);
}
public int occurs(String str, String subStr) {
int occurrences = 0;
int fromIndex = 0;
while (fromIndex > -1) {
fromIndex = str.indexOf(subStr, occurrences == 0 ? fromIndex : fromIndex + subStr.length());
if (fromIndex > -1) {
occurrences++;
}
}
return occurrences;
}
}

