Results 1 to 7 of 7
  1. #1
    berkeleybross's Avatar
    berkeleybross is offline Senior Member
    Join Date
    Feb 2010
    Location
    England
    Posts
    187
    Rep Power
    5

    Default Limit number of cols in JTextArea (again)

    Hey all,

    A while ago I started this thread, which I thought was solved.
    Unfortunately its not working again.

    Basically, I want to limit the number of characters in a line and the number of lines in a JTextArea.
    No line should ever be able to exceed x characters, and there should never be more than y lines, so I cant just limit the total number of characters.

    I'm currently extending a PlainDocument:
    Java Code:
    public class addressDocument extends PlainDocument{
        private int myCols;
        private int myRows;
        private JTextArea myEditorPane;
    
        public addressDocument (int cols, int rows, JTextArea editorPane) {
            myCols = cols;
            myRows = rows;
            myEditorPane = editorPane;
        }
    
        @Override
        public void insertString(int offset, String str, AttributeSet a) throws BadLocationException {
            super.insertString(offset, str, a);
    
            String lines[] = myEditorPane.getText().split("\r\n|\r|\n");
    
            if (lines.length > myRows) {
                java.awt.Toolkit.getDefaultToolkit().beep();
                remove(offset, str.length());
                throw new BadLocationException(str, offset);
            }
    
            for (int i = 0; i < lines.length; i++) {
                if (lines[i].length() > myCols) {
                    java.awt.Toolkit.getDefaultToolkit().beep();
                    remove(offset, str.length());
                    throw new BadLocationException(str, offset);
                }
            }
        }
    }
    This does work, but I've discovered a few flaws in it, which I cant resolve:

    When the user deletes an end of line character, the row below is moved up a row (as expected). However this means that the line could exceed the character limit (potentially be twice as long as allowed).
    I tried to override the remove method but it resulted in failure and i couldnt delete anything.

    secondly, the user can make as many new lines as they want, but are stopped from writing any characters to the lines past the limit. I want to stop any new lines from being made as well as stopping characters.

    thirdly, i seem to be getting this error message whenever I have two lines which are at maximum width, and when the caret is at the end of that line:
    Java Code:
    Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 30
            at sun.font.FontDesignMetrics.charsWidth(FontDesignMetrics.java:492)
            at javax.swing.text.Utilities.getTabbedTextOffset(Utilities.java:381)
            at javax.swing.text.Utilities.getTabbedTextOffset(Utilities.java:302)
            at javax.swing.text.Utilities.getTabbedTextOffset(Utilities.java:286)
            at javax.swing.text.PlainView.viewToModel(PlainView.java:403)
            at javax.swing.plaf.basic.BasicTextUI$RootView.viewToModel(BasicTextUI.java:1540)
            at javax.swing.plaf.basic.BasicTextUI.viewToModel(BasicTextUI.java:1089)
            at javax.swing.text.DefaultCaret.positionCaret(DefaultCaret.java:292)
            at javax.swing.text.DefaultCaret.adjustCaret(DefaultCaret.java:497)
            at javax.swing.text.DefaultCaret.adjustCaretAndFocus(DefaultCaret.java:485)
            at javax.swing.text.DefaultCaret.mousePressed(DefaultCaret.java:475)
            at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:263)
            at java.awt.Component.processMouseEvent(Component.java:6260)
            at javax.swing.JComponent.processMouseEvent(JComponent.java:3255)
            at java.awt.Component.processEvent(Component.java:6028)
            at java.awt.Container.processEvent(Container.java:2041)
            at java.awt.Component.dispatchEventImpl(Component.java:4630)
            at java.awt.Container.dispatchEventImpl(Container.java:2099)
            at java.awt.Component.dispatchEvent(Component.java:4460)
            at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
            at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4235)
            at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
            at java.awt.Container.dispatchEventImpl(Container.java:2085)
            at java.awt.Window.dispatchEventImpl(Window.java:2475)
            at java.awt.Component.dispatchEvent(Component.java:4460)
            at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
            at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
            at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
            at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
            at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
    I realise I may not be clear so please ask if you need more information.

    Thanks for your time,
    Berkeleybross

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

  3. #3
    berkeleybross's Avatar
    berkeleybross is offline Senior Member
    Join Date
    Feb 2010
    Location
    England
    Posts
    187
    Rep Power
    5

    Default

    Hi Fubarable,
    I've attached a very basic SSCCE in a zip. I think it shows all my problems :)

    Berkeleybross
    Attached Files Attached Files

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    I think that you may have better luck with this if you use a DocumentFilter rather than override Document. It will allow you to check proposed changes to the document before they are allowed. Check out the API on this and see if it may help you.

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    I shouldn't do this, but I mean something like this:
    Java Code:
    import java.awt.Font;
    import javax.swing.JFrame;
    import javax.swing.JTextArea;
    import javax.swing.WindowConstants;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Document;
    import javax.swing.text.DocumentFilter;
    import javax.swing.text.PlainDocument;
    
    /**
     * @author Berkeleybross
     */
    public class BBrossMain {
    
       public static void main(String[] args) {
          initComponents();
       }
    
       private static void initComponents() {
    
          JFrame mainFrame = new JFrame("SSCCEE");
          mainFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    
          JTextArea addressTextArea = new JTextArea(6, 30);
          addressTextArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); //!! added
          addressTextArea.setEditable(true);
    
          //!! addressTextArea.setDocument(new AddressDocument(6, 30, addressTextArea));
          ((PlainDocument)addressTextArea.getDocument()).setDocumentFilter(new AddressDocumentFilter(6, 30));
    
          mainFrame.getContentPane().add(addressTextArea);
          mainFrame.pack();
          mainFrame.setLocationRelativeTo(null);
          mainFrame.setVisible(true);
       }
    
    }
    
    class AddressDocumentFilter extends DocumentFilter {
       private int maxRows;
       private int maxCols;
    
       public AddressDocumentFilter(int maxRows, int maxCols) {
          this.maxRows = maxRows;
          this.maxCols = maxCols;
       }
    
       private boolean testString(String text) {
          String[] lines = text.split("\n");
          if (lines.length > maxRows) {
             return false;
          }
          for (String line : lines) {
             if (line.length() > maxCols) {
                return false;
             }
          }
          return true;
       }
    
       @Override
       public void insertString(FilterBypass fb, int offset, String insertString, AttributeSet attr)
                throws BadLocationException {
          Document doc = fb.getDocument();
          String text = doc.getText(0, doc.getLength());
          StringBuilder sb = new StringBuilder(text);
          sb.insert(offset, insertString);
          if (testString(sb.toString())) {
             super.insertString(fb, offset, insertString, attr);
          } else {
             java.awt.Toolkit.getDefaultToolkit().beep();
          }
       }
    
       @Override
       public void replace(FilterBypass fb, int offset, int length, String replaceText,
                AttributeSet attrs) throws BadLocationException {
          Document doc = fb.getDocument();
          String text = doc.getText(0, doc.getLength());
          StringBuilder sb = new StringBuilder(text);
          sb.replace(offset, offset + length, replaceText);
    
          if (testString(sb.toString())) {
             super.replace(fb, offset, length, replaceText, attrs);
          } else {
             java.awt.Toolkit.getDefaultToolkit().beep();
          }
       }
    
       @Override
       public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
          Document doc = fb.getDocument();
          String text = doc.getText(0, doc.getLength());
          StringBuilder sb = new StringBuilder(text);
    
          sb.delete(offset, offset + length);
          if (testString(sb.toString())) {
             super.remove(fb, offset, length);
          } else {
             java.awt.Toolkit.getDefaultToolkit().beep();
          }
       }
    }

  6. #6
    berkeleybross's Avatar
    berkeleybross is offline Senior Member
    Join Date
    Feb 2010
    Location
    England
    Posts
    187
    Rep Power
    5

    Default

    Hi Fubarable,
    Thanks for the help, much appreciated.

    I made one small correction to it, so that trailing blank lines are not allowed either.

    Java Code:
        private boolean testString(String text) {
            String[] lines = text.split("\n", -1);  // <- "-1" stops split removing trailing lines
            
            if (lines.length > maxRows) {
                return false;
            }
            for (String line : lines) {
                if (line.length() > maxCols) {
                    return false;
                }
            }
            return true;
        }
    Again, thanks for the help. I've been trying to do it for a week now :$
    Ill rep you now and mark complete :)

    Berkeleybross

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

Similar Threads

  1. Limit number of cols in JTextArea
    By berkeleybross in forum AWT / Swing
    Replies: 6
    Last Post: 06-27-2010, 04:20 PM
  2. jtextfield limit?
    By devstarter in forum New To Java
    Replies: 1
    Last Post: 03-01-2010, 07:17 PM
  3. JTextArea on PopUp -JTextArea isn't editable
    By Richy76 in forum AWT / Swing
    Replies: 3
    Last Post: 02-01-2010, 08:51 PM
  4. Can you Limit JSpinners??
    By ashton in forum New To Java
    Replies: 1
    Last Post: 02-09-2009, 07:10 AM
  5. Limit of String
    By javaplus in forum New To Java
    Replies: 5
    Last Post: 11-19-2007, 05:48 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •