-1

I've made a documentlistener that will call a method when text is inserted. It works but the problem is that it acts as if it's in a loop and is kept being called.
The method uses swingutilties.invokelater from inside the method.

   private void addNewLine() {
       SwingUtilities.invokeLater( () -> {
        textArea.append(System.getProperty("line.separator")+"hey");
       });
   }


    private final DocumentListener addNewLine = Handlers.forDocumentUpdate((event) -> {
         addNewLine();
    });

    @SuppressWarnings("serial")
    static DocumentListener forDocumentUpdate(Consumer<? super DocumentEvent> eventHandler) {
    return new DocumentListener() {
        @Override
        public void insertUpdate(DocumentEvent event) {
            eventHandler.accept(event);
        }
        @Override
        public void removeUpdate(DocumentEvent event) {
        }
        @Override
        public void changedUpdate(DocumentEvent event) {
        }
      };
    }
Johnnie
  • 21
  • 4
  • 1
    Post a [mcve].. – user1803551 Nov 28 '17 at 10:35
  • Don't update the `Document` from within a `DocumentListener`, this can cause a mutation exception or, as you seem to have discovered, other unusual behaviours. Instead, consider using a `DocumentFilter` – MadProgrammer Nov 28 '17 at 10:55
  • Instead of trying to find a "work around" to you problem, start by approaching it with the best tools for the job, have a look at [TransferHandler](https://docs.oracle.com/javase/tutorial/uiswing/dnd/transferhandler.html) – MadProgrammer Nov 28 '17 at 11:01
  • Well, doing it through TransferHandler would be a waste because I would have to rewrite alot of code, when I literally want to run one line of code. I was trying to do it through TransferHandler for a few hours. I'm not really familiar with documentfilter, but I will look at it. I think it could be better if it could potentially ignore any changes made by the filter. – Johnnie Nov 28 '17 at 11:07

1 Answers1

0

Before I had used DocumentListener to do the task, but there was a problem with recursive looping. The proper way is to add a DocumentFilter that will simply add a newline along with the code that inserts the original text to be inserted.

((AbstractDocument) textArea.getDocument()).
            setDocumentFilter(new NewLineFilter()); 

public class NewLineFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb,int offs,String str,AttributeSet a)
        throws BadLocationException {
}
@Override 
public void replace(FilterBypass fb, int offs,int length, String str, AttributeSet a)
        throws BadLocationException {
    System.out.println("in replace");
    super.replace(fb,offs,length,str,a);
    super.insertString(fb, fb.getDocument().getLength(), System.lineSeparator(), a);
}}

If you know a better way to write this or If you know of a way to make a handler that would create an anonymous class for this that would be great. I couldn't use Consumer because replace() has more than one parameter. I could make another functional interface, but I don't know how useful it would be. I figure could potentially just reuse this class if I need to the same thing again.

Johnnie
  • 21
  • 4