我需要实现我的自定义DefaultComboboxModel。这样做的原因是每次我打电话给
DefaultComboBoxModel model = (DefaultComboBoxModel)getModel();
model.removeAllElements();
或
model.addElement(Object);
或
model.insertElementAt(Object,int)
我看到它会自动触发ItemStateChanged事件。这导致一些随机项自动从列表中选择。这不是我想要的,因为它使用随机选择的项目填充可编辑的JTextField。
这是我在使用自定义Itemlistener中的Thread.dumpStack()进行调试时看到的堆栈跟踪,我在调用上述方法时看到:
at javax.swing.JComboBox.fireItemStatehanged(Unknown source)
at javax.swing.JComboBox.selectedItemChanged(Unknown source)
at javax.swing.JComboBox.contentsChanged(Unknown source)
at javax.swing.JComboBox.fireContentsChanged(Unknown source)
at javax.swing.JComboBox.setSelectedItem(Unknown source)
at javax.swing.JComboBox.addElement(Unknown source)
我已经尝试在更新模型之前使用setSelectedIndex(-1),并且在模型更新之后也是如此,但同样的问题。我想让自定义模型成为可行的方法。
问题是如何实现我的自定义组合框模型?我只是扩展DefaultComboBoxModel吗?我是否必须覆盖DefaultComboBoxMode中的所有方法?
以下是我到目前为止的情况。但是,如果您在下面看到,我没有引用实际的矢量列表来删除该项目。如果我在自定义AutocompleteComboBoxModel中声明了一个Vector列表字段,那么我是否需要覆盖所有方法以避免其他SWING代码引用超类中的Vector?
记住我的目标是永远不要让模型自动调用setSelectedItem(Object),因为这似乎会导致问题,除非有更好的方法来做到这一点。
public class AutocompleteComboBoxModel extends DefaultComboBoxModel{
public void removeElementAt(int index){
list.removeElementAt(index);
fireIntervalRemoved(this, index, index);
}
}
这也是我调用模型操作方法的方法:
public class AutocompleteDocumentListener implementts DocumentListener{
JTextField tf;
public AutocompleteDocumentListener (JTextfield tf){
this.tf = tf;
}
@Override
public void changedUpdate(DocumentEvent e){
}
@Override
public void insertUpdate(DocumentEvent e){
update();
}
@Override
public void removeUpdate(DocumentEvent e){
update();
}
public void update(){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
performSearch(tf.getText());//Search user input
}
)
}
}
编辑:只是想提一下,这种奇怪的行为只会在我输入速度非常快时发生。如果我键入慢,那么SWING不会自动选择随机项。那么,如果我使用SwingUtlities.invokeLater,为什么会在快速键入时出现这种情况?目前,当SWING调用setSelectedItem(Object)时,此触发事件是否会在其他invokeLater请求之前执行?
编辑:我正在移除ItemListener但仍无法正常工作。然后我继续去除JComboBox KeyListeners,ActionListeners,ComponentListeners和FocusListeners,它仍然自动选择Item。似乎在invokeLater完成之后的某个时间我看到项目被选中,可能是因为我还在JTextField上输入:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at com.artificialmed.coderdx.encoder.TermSelectionListener.itemStateChanged(TermSelectionListener.java:23)
at javax.swing.JComboBox.fireItemStateChanged(Unknown Source)
at javax.swing.JComboBox.selectedItemChanged(Unknown Source)
at javax.swing.JComboBox.contentsChanged(Unknown Source)
at javax.swing.AbstractListModel.fireContentsChanged(Unknown Source)
at javax.swing.DefaultComboBoxModel.setSelectedItem(Unknown Source)
at javax.swing.JComboBox.setSelectedItem(Unknown Source)
at javax.swing.JComboBox.setSelectedIndex(Unknown Source)
at javax.swing.JComboBox.selectWithKeyChar(Unknown Source)
at javax.swing.plaf.basic.BasicComboBoxUI$Handler.keyPressed(Unknown Source)
at java.awt.Component.processKeyEvent(Unknown Source)
at javax.swing.JComponent.processKeyEvent(Unknown Source)
at javax.swing.JComboBox.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)
提前致谢。
答案 0 :(得分:1)
addElement(...)或insertElementAt(...)方法不应导致生成ItemStateChanged事件,因为选择不应更改。
removeAll()元素会导致所选项目被取消选中,因此生成事件是有意义的。
一些解决方案:
仅处理所选的"项目"事件。这样当您删除所有项目时,忽略"项目取消选择"事件
在状态更改代码时调用的逻辑应该调用getSelectedItem()。如果此值为null,则表示您没有做任何事情。
a)删除监听器,b)调用removeAll()方法,c)添加监听器。由于在调用removeAll()方法时侦听器不存在,因此不会生成任何事件。