I am using JTextArea in JScrollPane
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.
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.
There are 2 stages:
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!
Does anyone have an idea?
I know that i will have to use DocumentFilter OR StyledDocument.
Here is sample code that limit only the lines to 3:(but not the chars in row to 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;
}
}
You can use JTextArea#setLineWrap(true) by default is set to false. Sets the line-wrapping policy of the text area. If set to true the lines will be wrapped if they are too long to fit within the allocated width. If set to false, the lines will always be unwrapped.
The JTextArea class provides a component that displays multiple lines of text and optionally allows the user to edit the text.
selectAll(); JTextArea0. replaceSelection(""); This selects the entire textArea and then replaces it will a null string, effectively clearing the JTextArea.
Constructs a new TextArea. A default model is set, the initial string is null, and rows/columns are set to 0.
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.occurs
method is as follows:
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;
}
Here's my version, based on Nick Holt's version.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With