1

JTextField's SetText method throws an exception whenever I try to set the contents while the field has focus. I need that to change, because I want to input a very precise number of characters, and once that character count is reached the field needs to be cleared while still having focus so the next set of characters can immediately be added without pushing any buttons.

I tried creating a static method that would re-create the text field from scratch every time it filled up, allowing a sort of recursive regeneration of the field each time. The method simply didn't do anything. For reference, basically everything in this program is static because it's a very simple application and I basically just want to access every important variable from "main".

Trying to set the text while the field has focus shows the following:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
    at javax.swing.text.AbstractDocument.writeLock(Unknown Source)
    at javax.swing.text.AbstractDocument.replace(Unknown Source)
    at javax.swing.text.JTextComponent.setText(Unknown Source)
    at onlypack.ProgramMain$3.insertUpdate(ProgramMain.java:118)
    at javax.swing.text.AbstractDocument.fireInsertUpdate(Unknown Source)
    at javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
    at javax.swing.text.AbstractDocument.insertString(Unknown Source)
    at javax.swing.text.PlainDocument.insertString(Unknown Source)
    at javax.swing.text.AbstractDocument.replace(Unknown Source)
    at javax.swing.text.JTextComponent.replaceSelection(Unknown Source)
    at javax.swing.text.DefaultEditorKit$DefaultKeyTypedAction.actionPerformed(Unknown Source)
    at javax.swing.SwingUtilities.notifyAction(Unknown Source)
    at javax.swing.JComponent.processKeyBinding(Unknown Source)
    at javax.swing.JComponent.processKeyBindings(Unknown Source)
    at javax.swing.JComponent.processKeyEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
double-beep
  • 5,031
  • 17
  • 33
  • 41
Ty Brantner
  • 85
  • 1
  • 7
  • perhaps create a subclass and override the behavior? I'm not super familiar with JTFs but that seems to be the advice of the javadocs for creating custom fields – Jeeter Jul 23 '19 at 18:55
  • can you unfocus the element, set content and focus element again? – Cheaker Jul 23 '19 at 18:57
  • @Cheaker Is there a way that I can unfocus the text field without focusing another UI element? I don't have any other JWhatsits to set the focus to. I could create one specifically to shift focus away from the text field, but I thought maybe I was being naive and missing something obvious about JTextFIelds. It seems silly you can't modify the contents while it's focused, feels like Java trying to force you to do things the way it thinks professionals should do them. – Ty Brantner Jul 23 '19 at 19:01
  • this may work `textfield.setFocusable(false)` , otherwise take a look here https://stackoverflow.com/questions/10773132/how-to-unfocus-a-jtextfield – Cheaker Jul 23 '19 at 19:11
  • @Cheaker Okay, according to that you can't modify the document from inside a Document LIstener (heaven only knows why), and you'd have to write a custom variant of that class to circumvent this. I'm not well enough versed in Java to do that. I'll leave the question open in case someone else knows a solution, though. – Ty Brantner Jul 23 '19 at 19:21

1 Answers1

3

you can't modify the document from inside a Document LIstener

Correct, you need to wait until the Document is in a state to accept input.

One way to do this is to wrap your code in the DocumentListener in a SwingUtilties.invokeLater(). This will place the code at the end of the Event Dispatch Thread and it will execute after the Document has finished updating itself.

Another option, instead of using a DocumentListener, it to use a DocumentFilter. This intercepts the text BEFORE it is added to the Document. So you could just simply clear the Document when the specified number of characters has been input. Read the section from the Swing tutorial on Implement a DocumentFilter for more information.

camickr
  • 321,443
  • 19
  • 166
  • 288