正如标题所说,当我从 jcombobox 弹出菜单中选择一个项目时,没有任何不好的事情发生,但是当我回到编辑器(再次输入文本)时,动作执行事件会无缘无故地立即触发。
我创建了一个自定义的 jcombox 模型和编辑器(并创建了一些代码行,将问题增强为自动触发的动作事件)。
示例 (sscce)
import Controllers.CustomComboBoxModel;
import Controllers.ProductosItemEditor;
//import Store.util.DatabaseHelper;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.hibernate.HibernateException;
public class CustomComboBoxEditor {
public static void main(String[] args) {
new CustomComboBoxEditor();
}
public CustomComboBoxEditor() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final JComboBox cb = new JComboBox();
cb.setEditable(true);
cb.setEditor(new ProductosItemEditor());
CustomComboBoxModel model = new CustomComboBoxModel();
cb.setModel(model);
cb.addItem("Apple");
cb.addItem("Banana");
cb.addItem("Orange");
cb.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent event) {
System.out.println("typed text " + cb.getEditor().getItem());
//populateModel(cb.getEditor().getItem().toString());
}
/*
public void populateModel(String text) throws HibernateException {
List l = DatabaseHelper.GetProductsBy(text);
for (Object object : l) {
cb.addItem(object);
}
}*/
});
cb.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
JComboSearcherActionPerformed(evt);
}
private void JComboSearcherActionPerformed(ActionEvent evt) {
System.out.println(" action perform combobox " + cb.getSelectedItem());
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(cb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
我的编辑
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;
import java.lang.reflect.Method;
import javax.swing.JTextField;
import javax.swing.ComboBoxEditor;
import javax.swing.JButton;
import javax.swing.JPanel;
public class ProductosItemEditor extends JPanel implements ComboBoxEditor {
private JTextField txtField = new JTextField();
private JButton clearButton = new JButton();
private Object oldValue;
/**
*
*/
public ProductosItemEditor() {
setLayout(new BorderLayout());
clearButton.setBackground(new java.awt.Color(255, 255, 255));
clearButton.setForeground(new java.awt.Color(0, 51, 51));
clearButton.setText("X");
clearButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
txtField.setText("");
txtField.requestFocusInWindow();
//remove the above line and an action performed event of combobox
// gets fired automaticaly
}
});
add(txtField, BorderLayout.CENTER);
add(clearButton, BorderLayout.EAST);
}
@Override
public Component getEditorComponent() {
return this;
}
public String getText() {
return txtField.getText();
}
@Override
public Object getItem() {
Object newValue = txtField.getText();
if (oldValue != null && !(oldValue instanceof String)) {
if (newValue.equals(oldValue.toString())) {
return oldValue;
} else {
Class<?> cls = oldValue.getClass();
try {
Method method = cls.getMethod("valueOf", new Class[]{String.class});
newValue = method.invoke(oldValue, new Object[]{txtField.getText()});
} catch (Exception ex) {
}
}
}
return newValue;
}
@Override
public void setItem(Object anObject) {
String text;
if (anObject != null) {
text = anObject.toString();
oldValue = anObject;
} else {
text = "";
}
}
@Override
public void selectAll() {
txtField.selectAll();
}
@Override
public void addActionListener(ActionListener l) {
txtField.addActionListener(l);
}
@Override
public void removeActionListener(ActionListener l) {
txtField.removeActionListener(l);
}
@Override
public void addKeyListener(KeyListener e) {
txtField.addKeyListener(e);
}
@Override
public void removeKeyListener(KeyListener e) {
txtField.removeKeyListener(e);
}
@Override
public void addNotify() {
super.addNotify();
txtField.requestFocusInWindow();
}
}
我的模型
import javax.swing.AbstractListModel;
import javax.swing.MutableComboBoxModel;
import java.util.*;
import java.io.Serializable;
import java.util.logging.Logger;
public final class CustomComboBoxModel extends AbstractListModel implements MutableComboBoxModel, Serializable {
ArrayList<Object> objects;
Object selectedObject;
/**
* Constructs a DefaultComboBoxModel object initialized with a vector.
*
* @param v a Vector object ...
*/
public CustomComboBoxModel(ArrayList v) {
objects = v;
if (getSize() > 0) {
selectedObject = getElementAt(0);
}
}
/**
*
*/
public CustomComboBoxModel() {
this.objects = new ArrayList<Object>();
}
// implements javax.swing.ComboBoxModel
/**
* Set the value of the selected item. The selected item may be null.
* <p>
*
* @param anObject The combo box value or null for no selection.
*/
public void setSelectedItem(Object anObject) {
if (anObject != null) {
selectedObject = anObject;
// fireContentsChanged(this, -1, -1);
// quit above line and bug return (the action perform gets fired automaticaly
}
}
// implements javax.swing.ComboBoxModel
public Object getSelectedItem() {
return selectedObject;
}
// implements javax.swing.ListModel
public int getSize() {
return objects.size();
}
// implements javax.swing.ListModel
public Object getElementAt(int index) {
if (index >= 0 && index < objects.size()) {
return objects.get(index);
} else {
return null;
}
}
/**
* Returns the index-position of the specified object in the list.
*
* @param anObject
* @return an int representing the index position, where 0 is the first position
*/
public int getIndexOf(Object anObject) {
return objects.indexOf(anObject);
}
// implements javax.swing.MutableComboBoxModel
public void addElement(Object anObject) {
objects.add(anObject);
fireIntervalAdded(this, objects.size() - 1, objects.size() - 1);
if (objects.size() == 1 && selectedObject == null && anObject != null) {
setSelectedItem(anObject);
}
}
// implements javax.swing.MutableComboBoxModel
public void insertElementAt(Object anObject, int index) {
objects.add(index, anObject);
fireIntervalAdded(this, index, index);
}
// implements javax.swing.MutableComboBoxModel
public void removeElementAt(int index) {
if (getElementAt(index) == selectedObject) {
if (index == 0) {
setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1));
} else {
setSelectedItem(getElementAt(index - 1));
}
}
objects.remove(index);
fireIntervalRemoved(this, index, index);
}
// implements javax.swing.MutableComboBoxModel
public void removeElement(Object anObject) {
int index = objects.indexOf(anObject);
if (index != -1) {
removeElementAt(index);
}
}
/**
* Empties the list.
*/
public void removeAllElements() {
if (objects.size() > 0) {
int firstIndex = 0;
int lastIndex = objects.size() - 1;
objects.clear();
selectedObject = null;
fireIntervalRemoved(this, firstIndex, lastIndex);
} else {
selectedObject = null;
}
}