使用setModel()更新JComboBox时发生java.lang.IllegalStateException?

使用setModel()更新JComboBox时发生java.lang.IllegalStateException?,java,swing,jcombobox,illegalstateexception,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 jav

我试图用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) {
    }
}

SwingUtilities.invokeLater()中的
insertUpdate(DocumentEvent e)
中包装代码。这样做会产生一些非常奇怪的结果。API旨在防止线程更新和可能导致无限循环的潜在修改


在这种情况下,文本字段被修改,
文档
被更新,
文档监听器
被通知,并且您尝试再次更改该字段,这将再次开始循环,除了
文档
有一个防护装置防止您执行此操作,因此出现了
异常

你需要做的是两件事


  • 您需要在通知
    DocumentListener
    后更新文本字段。如前所述,这可以通过使用
    SwingUtilities.invokeLater

  • 提供某种标志,这样您就不会因为
    DocumentListener
    事件而修改字段,从而尝试修改字段上的事件…是否感到困惑

  • 基本上,此示例使用
    SwingUtilities.invokeLater
    DocumentListener
    完成其事件通知后更新字段,并使用一个简单的
    boolean
    标志提供一种“忽略”我们触发的更新的方法

    这很混乱,但它会完成工作…主要是

    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.SwingUtilities;
    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) {
        }
    
        boolean beenModified = false;
    
        @Override
        public void insertUpdate(DocumentEvent e) {
    
            if (!beenModified) {
                beenModified = true;
    
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
    
                        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();
    
                        beenModified = false;
                    }
                });
    
            }
        }
    
        @Override
        public void removeUpdate(DocumentEvent e) {
        }
    }
    
    导入java.awt.BorderLayout;
    导入java.awt.Color;
    导入java.awt.Dimension;
    导入javax.swing.DefaultComboxModel;
    导入javax.swing.JComboBox;
    导入javax.swing.JFrame;
    导入javax.swing.JPanel;
    导入javax.swing.JTextField;
    导入javax.swing.JToolBar;
    导入javax.swing.SwingUtilities;
    导入javax.swing.event.DocumentEvent;
    导入javax.swing.event.DocumentListener;
    公共类TestFrame扩展JFrame实现DocumentListener{
    私有静态最终长serialVersionUID=1L;
    //工具条
    私有JToolBar topToolBar;
    私有JTextField-wordSearchField;
    私人JComboBox wordSearchTips;
    //窗口大小
    专用静态最终整数宽度=700;
    专用静态最终内部高度=500;
    公共测试框架(){
    }
    公共静态void main(字符串[]argv){
    新建TestFrame().CreateUI();
    }
    public void CreateUI(){
    setPreferredSize(新尺寸(宽度、高度));
    可设置大小(假);
    setLayout(新的BorderLayout());
    //底部
    JPanel bottom=新的JPanel();
    底部。设置首选尺寸(新尺寸(宽度,480));
    bottom.setLayout(新的BorderLayout());
    //顶
    topToolBar=新的JToolBar();
    topToolBar.setBackground(颜色:白色);
    setPreferredSize(新尺寸(宽度,30));
    wordSearchTips=newjcombobox();
    wordSearchTips.setEditable(true);
    wordSearchTips.setSelectedIndex(-1);
    wordSearchField=(JTextField)wordSearchTips.getEditor()
    .getEditorComponent();
    wordSearchField.getDocument().addDocumentListener(此);
    添加(wordSearchTips);
    添加(顶部工具栏,BorderLayout.NORTH);
    添加(底部,BorderLayout.SOUTH);
    包装();
    setVisible(真);
    }
    @凌驾
    公共作废更改日期(记录事件e){
    }
    布尔beenModified=false;
    @凌驾
    公共作废插入更新(文档事件e){
    如果(!beenModified){
    beenModified=真;
    SwingUtilities.invokeLater(新的Runnable(){
    @凌驾
    公开募捐{
    String关键字=wordSearchField.getText().trim();
    DefaultComboxModel m=新的DefaultComboxModel();
    对于(int i=0;i<10;i++){
    m、 加法(i+);
    }
    wordSearchTips.setModel(m);
    wordSearchTips.setSelectedIndex(-1);
    ((JTextField)wordSearchTips.getEditor().getEditorComponent())
    .setText(关键字);
    wordSearchTips.showPopup();
    beenModified=假;
    }
    });
    }
    }
    @凌驾
    公共作废移除更新(文档事件e){
    }
    }
    
    这样做会产生一些非常奇怪的结果。API旨在防止线程更新和可能导致无限循环的潜在修改


    在这种情况下,文本字段被修改,
    文档
    被更新,
    文档监听器
    被通知,并且您尝试再次更改该字段,这将再次开始循环,除了
    文档
    有一个防护装置防止您执行此操作,因此出现了
    异常

    你需要做的是两件事


  • 您需要在通知
    DocumentListener
    后更新文本字段。如前所述,这可以通过使用
    SwingUtilities.invokeLater

  • 提供某种标志,这样您就不会因为
    DocumentListener
    事件而修改字段,从而尝试修改字段上的事件…是否感到困惑

  • 基本上,此示例使用
    SwingUtilities.invokeLater
    DocumentListener
    完成其事件通知后更新字段,并使用一个简单的
    boolean
    标志提供一种“忽略”我们触发的更新的方法

    这很乱,但它能把工作做好
    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.SwingUtilities;
    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) {
        }
    
        boolean beenModified = false;
    
        @Override
        public void insertUpdate(DocumentEvent e) {
    
            if (!beenModified) {
                beenModified = true;
    
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
    
                        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();
    
                        beenModified = false;
                    }
                });
    
            }
        }
    
        @Override
        public void removeUpdate(DocumentEvent e) {
        }
    }