使用setModel()更新JComboBox时是否存在java.lang.IllegalStateException?

时间:2014-05-15 06:47:30

标签: java swing jcombobox illegalstateexception

我试图用setModel()更新JComboBox。但是,它会抛出java.lang.IllegalStateException。 具体来说,我使用JTextField指向JComboBox的可编辑组件,并在每次JTextField接收新输入时更新JComboBox。

谁能告诉我原因?

package ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class TestFrame extends JFrame implements DocumentListener {

    private static final long serialVersionUID = 1L;

    // tool bar
    private JToolBar topToolBar;
    private JTextField wordSearchField;
    private JComboBox<String> wordSearchTips;

    // window size
    private static final int width = 700;
    private static final int height = 500;

    public TestFrame() {
    }

    public static void main(String[] argv) {
        new TestFrame().CreateUI();
    }

    public void CreateUI() {
        setPreferredSize(new Dimension(width, height));
        setResizable(false);
        setLayout(new BorderLayout());

        // bottom
        JPanel bottom = new JPanel();
        bottom.setPreferredSize(new Dimension(width, 480));
        bottom.setLayout(new BorderLayout());

        // top
        topToolBar = new JToolBar();
        topToolBar.setBackground(Color.WHITE);
        topToolBar.setPreferredSize(new Dimension(width, 30));

        wordSearchTips = new JComboBox<String>();
        wordSearchTips.setEditable(true);
        wordSearchTips.setSelectedIndex(-1);
        wordSearchField = (JTextField) wordSearchTips.getEditor()
                .getEditorComponent();
        wordSearchField.getDocument().addDocumentListener(this);

        topToolBar.add(wordSearchTips);

        add(topToolBar, BorderLayout.NORTH);
        add(bottom, BorderLayout.SOUTH);

        pack();
        setVisible(true);

    }

    @Override
    public void changedUpdate(DocumentEvent e) {

    }

    @Override
    public void insertUpdate(DocumentEvent e) {

        String keyword = wordSearchField.getText().trim();
        DefaultComboBoxModel<String> m = new DefaultComboBoxModel<String>();
        ;
        for (int i = 0; i < 10; i++) {
            m.addElement(i + "");
        }
        wordSearchTips.setModel(m);
        wordSearchTips.setSelectedIndex(-1);
        ((JTextField) wordSearchTips.getEditor().getEditorComponent())
                .setText(keyword);
        wordSearchTips.showPopup();
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
    }
}

以下是例外:

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 javax.swing.plaf.metal.MetalComboBoxEditor$1.setText(Unknown Source)
    at javax.swing.plaf.basic.BasicComboBoxEditor.setItem(Unknown Source)
    at javax.swing.JComboBox.configureEditor(Unknown Source)
    at javax.swing.plaf.basic.BasicComboBoxUI$Handler.propertyChange(Unknown Source)
    at javax.swing.plaf.basic.BasicComboBoxUI$PropertyChangeHandler.propertyChange(Unknown Source)
    at javax.swing.plaf.metal.MetalComboBoxUI$MetalPropertyChangeListener.propertyChange(Unknown Source)
    at java.beans.PropertyChangeSupport.fire(Unknown Source)
    at java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
    at java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
    at java.awt.Component.firePropertyChange(Unknown Source)
    at javax.swing.JComboBox.setModel(Unknown Source)
    at ui.TestFrame.insertUpdate(TestFrame.java:94)
    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$200(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$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.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$1.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)

2 个答案:

答案 0 :(得分:2)

insertUpdate(DocumentEvent e)

中的SwingUtilities.invokeLater()传送您的代码

答案 1 :(得分:2)

这样做会产生一些非常奇怪的结果。 API旨在防止线程更新和可能导致无限循环的潜在修改

在这种情况下,文本字段已修改,Document已更新,DocumentListener会收到通知,您尝试再次更改字段,这将再次开始循环,但{{1}除外1}}有一个警卫阻止你做这件事,因此Document

你需要做的是两件事。

  1. 您需要在通知Exception后更新文本字段。如前所述,这可以通过使用DocumentListener
  2. 来实现
  3. 提供某种标记,这样您就不会尝试修改因SwingUtilities.invokeLater事件而导致修改字段导致的事件的字段而感到困惑吗?
  4. 基本上,此示例使用DocumentListenerSwingUtilities.invokeLater完成事件通知和简单DocumentListener标记后更新字段,以便为&#34提供方法;忽略&#34;我们已触发的更新...

    它很乱,但它会完成工作......主要是......

    boolean