使用setModel()更新JComboBox时发生java.lang.IllegalStateException?
我试图用setModel()更新JComboBox。但是,它抛出java.lang.IllegalStateException。 具体地说,我使用了一个JTextField来指向JComboBox的可编辑组件,并在JTextField每次收到新输入时更新JComboBox 谁能告诉我原因吗使用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
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) {
}
}