В Java/Swing есть ли способ законно попытаться изменить уведомление?

Мне было интересно, есть ли какая-то магия, которую я могу использовать, чтобы обойти IllegalStateException и позволить JTextField «попытаться изменить в уведомлении» или, другими словами, установить свой собственный текст, если его слушатель запущен.

К вашему сведению, я пытаюсь запрограммировать функцию автозаполнения, которая возвращает наиболее вероятное совпадение в диапазоне из 12 перечислений в ответ на ввод пользователя в JTextField.

Вот пример кода. Вы должны простить мой неуклюжий алгоритм, который выдает результаты перечисления. Я выделил код, вызывающий исключение, комментарием:

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());
                }

            }
        });

person Arvanem    schedule 30.08.2010    source источник
comment
Если код Enum затрудняет чтение, можете ли вы вынуть его, поместить постоянную строку в setText() и по-прежнему получать Exception?   -  person PeterMmm    schedule 30.08.2010
comment
@PeterMmm: Да, исключение по-прежнему срабатывает даже с постоянной строкой и удалением всего кода перечисления.   -  person Arvanem    schedule 30.08.2010


Ответы (6)


Вам, вероятно, лучше использовать фильтр документов или пользовательский документ.

Что должны увидеть другие слушатели, если документ не останется прежним во время отправки события?

person Tom Hawtin - tackline    schedule 30.08.2010

Используйте SwingUtilities.invokeLater(), разместив там все модификации

person StanislavL    schedule 03.09.2010

Возможно, вы можете отложить setText() с потоком для запуска после завершения CaretUpdate().

person PeterMmm    schedule 30.08.2010
comment
+1 и спасибо за интересный ответ. Я попробую другой поток - программа уже работает в потоке Event-Dispatching? - person Arvanem; 30.08.2010
comment
Хотя в тексте Swing есть некоторые претензии к потокобезопасности, на самом деле это не работает. Если вы попробуете этот вариант, я предлагаю java.awt.EventQueue.invokeLater. Будьте осторожны при одновременной обработке нескольких обновлений. - person Tom Hawtin - tackline; 30.08.2010
comment
Как сказал Том, это может быть грязным решением (если вообще когда-либо). Вероятно, вы выбрали не тот прослушиватель событий, чтобы делать то, что хотите. Чтобы реализовать такие функции самостоятельно без глубоких знаний, свинг может быть очень разочаровывающим... - person PeterMmm; 30.08.2010

я нашел ту же проблему, но я нашел простое решение:

заблокируйте caretUpdate() с помощью логического значения if(false), пока вы устанавливаете текст в jTextField, а затем разблокируете его после . . что-то вроде этого:

логическое знак вставки = истина;

private void listValueChanged(javax.swing.event.ListSelectionEvent evt) { Caret = false; name.setText((String)list.getSelectedValue()); каретка = истина; }

private void nameCaretUpdate(javax.swing.event.CaretEvent evt) {
   if(caret){
    model = new DefaultListModel();
    this.fillList(name.getText());
    list.setModel(model);
    }
}
person mehemmel bachir    schedule 07.06.2011

Создайте пользовательский документ и переопределите метод insertString().

filenameText = new JTextField(new FilenameDocument(), "", 0);

...

 /**
 * document which adds .xml extension if not specified
 *
 */
private class FilenameDocument extends PlainDocument {

    @Override
    public void insertString(int offset, String insertedText, AttributeSet set)
    throws BadLocationException {
        if (offset == 0) {
        insertedText = insertedText.trim( );
        }
        super.insertString(offset, insertedText, set);
        if (filenameText != null) {
            final int caretPos = filenameText.getCaretPosition();
            String text = filenameText.getText().trim();
            if (text.indexOf('.') == -1) {
                filenameText.setText(text + ".xml");
                filenameText.setCaretPosition(caretPos);
            }

        }
    }
}

Обратите внимание, что вызов setText приведет к рекурсивному вызову insertString(), поэтому убедитесь, что у вас есть условие остановки.

person gerardw    schedule 02.11.2011

Я удивлен, что никто не ответил на этот вопрос, но не лучше ли было бы реализовать редактируемый JSpinner с SpinnerListModel ?

person Tim    schedule 19.01.2012