views:

89

answers:

3

Hi folks,

I was wondering if there is some sort of magic I can use to get around an IllegalStateException and allow a JTextField to "attempt to mutate in notification", or in other words to set its own text if its listener is triggered.

For your information, I am trying to program an auto-complete function which returns the most likely match in a range of 12 enums in response to a user's input in the JTextField.

Here is the code sample. You'll have to pardon my clumsy algorithm which creaks out enum results. I've highlighted the code which produces the exception with a comment:

jtfElement1.addCaretListener(new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent e) {                    
                String s = jtfElement1.getText();
                int[] attributes = new int[13];
                // iterate through each enum
                for (BaseEnumAttributes b: BaseEnumAttributes.values()) {
                    // iterate through the length of the current text in jtfElement1
                    for (int i = 0; i < s.length(); i++) {
                        if (s.length() <= b.toString().length()) {                                
                            if (b.toString().charAt(i) == s.charAt(i)) {
                                // increase the number of "hits" noted for that enum
                                attributes[b.ordinal()] = attributes[b.ordinal()] + 1;
                            }                                
                        }
                    }                        
                }
                int priorC = 0;
                int rightC = 0;                    
                // iterate through the "array" of enums to find the highest score
                for (int j = 0; j < attributes.length; j++) {
                    if (attributes[j] > priorC) {
                        priorC = attributes[j];
                        rightC = j;
                    }
                }                    
                if (!s.equals("")) {
                    // assign to b the Enum corresponding to the "array" with highest score
                    BaseEnumAttributes b = BaseEnumAttributes.values()[rightC];
                    iController.updateInputElement1String(b.toString());                        
                    // THIS TRIGGERS EXCEPTION 
                    jtfElement1.setText(b.toString());
                }

            }
        });
+1  A: 

Maybe you can delay the setText() with a Thread to run after caretUpdate() has terminated.

PeterMmm
+1 and thank you for the interesting answer. I'll try another thread - the program is already running on the Event-Dispatching thread?
Arvanem
Although there are some claims for thread-safety in Swing text, it doesn't really work. If you try this option, I suggest `java.awt.EventQueue.invokeLater`. Be careful about processing multiple updates at once.
Tom Hawtin - tackline
As Tom said, that could be a dirty solution (if ever). Probably you took the wrong event listener to do what you want to do. To implement that kind of features by yourself w/o deep knowledge, swing could be very frustrating ...
PeterMmm
+1  A: 

You are probably better off using a document filter or a custom document.

What are other listeners expected to see if the document doesn't stay the same during event dispatch?

Tom Hawtin - tackline
A: 

Use SwingUtilities.invokeLater() placing all the modifications there

StanislavL