Как ограничить количество строк и столбцов в JTextArea? - PullRequest
4 голосов
/ 26 января 2009

Я использую JTextArea в JScrollPane

Я хочу ограничить максимальное количество возможных строк и максимальное число символов в каждой строке.

Мне нужно, чтобы строка была точно такой же, как на экране, каждая строка будет заканчиваться символом '\ n' (если после нее будет другая строка), и пользователь сможет вставлять только X строк и Y символов в каждой строке .

Я пытался ограничить строки, но я не знаю точно, сколько строк у меня из-за переноса строк. Обтекание строк запускает новую строку визуально на экране (из-за ширины JTextArea), но в строка компонента - это на самом деле та же самая строка без '\ n' для обозначения новой строки. У меня нет идеи, как ограничить максимальное число символов в каждой строке при вводе.

Есть 2 этапа:

  1. Ввод строки - учтите, что пользователь не сможет набирать более X строк и Y символов в каждой строке. (даже если строка переносится только визуально или пользователь вводит '/ n')
  2. Вставьте строку в БД - после нажатия кнопки «ОК» преобразуйте строку, чтобы каждая строка заканчивалась на «/ n», даже если пользователь не набрал ее, а строка была перенесена только визуально.

Есть несколько проблем, если я посчитаю символы в строке и вставлю '/ n' в конце строки, поэтому я решил сделать это в два этапа. На первом этапе пользователь печатает, я бы предпочел только ограничить его визуально и вызвать перенос строк или что-то подобное. Только на втором этапе, когда я сохраняю строку, я добавлю '/ n', даже если пользователь не набрал ее в конце строк!

У кого-нибудь есть идея?


Я знаю, что мне придется использовать DocumentFilter ИЛИ StyledDocument.

Вот пример кода, который ограничивает только строки 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;
   }
}

Ответы [ 2 ]

1 голос
/ 18 марта 2010

Вот моя версия, основанная на версии Ника Холта.

Только для записей, это будет использоваться в прототипе и не было проверено много (если вообще).

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;
    }
}
1 голос
/ 30 сентября 2009

У меня сработало следующее:

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);
    }
  }
}

Где метод 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;
}
...