自定义jcomboxeditor触发自动jcombobox动作执行动作

时间:2013-07-29 22:56:42

标签: java swing text-editor jcombobox mode

正如tittle所说,当我从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;
        }
    }

1 个答案:

答案 0 :(得分:0)

现在我修复了问题并修改了我不想要的行为(当你在一个可编辑的组合框中输入文本时,列表中的第一个匹配项被放置为编辑器中的文本)我还修改了一些其他问题jcombobox动作无缘无故地执行了事件。所有这些问题都出现在模型中和编辑器中。

public class ProductosItemEditor extends JPanel implements ComboBoxEditor {

private JTextField txtField = new JTextField();
private JButton clearButton = new JButton();

private Object myObject;
private Object myReturnObject;

/**
 *
 */
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 Object getText() {
    return txtField.getText();
}

    @Override
    public Object getItem() {
//it's good for my you can implement your own method 
        ///or look at CustomComboBoxModel for studies porposes
        return "";


}

@Override
    public void setItem(Object anObject) {

    if (anObject != null) {
        myObject = anObject;
        myReturnObject = anObject;
        //I can now set whatever i want in the text feild            
        txtField.setText(myObject.toString());//<--

    } else {
        myReturnObject = "";
    }
}

@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) {
    if (e == null) {
        return;
    }
    txtField.addKeyListener(e);
}

@Override
    public void removeKeyListener(KeyListener e) {
    txtField.removeKeyListener(e);
}

@Override
    public void addNotify() {
    super.addNotify();
    txtField.requestFocusInWindow();
}

}

和模型(将数据存储在arrayList中)

    import javax.swing.AbstractListModel;
import javax.swing.MutableComboBoxModel;

import java.util.*;


import java.io.Serializable;


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); this line causes automatic jcombobox action performed events
        }
    }

    // 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;
        }
    }

}

我很高兴看到对此代码的检查有待改进,我希望有些机构可以使用它并节省一些时间