需要灵活的JComboBox Java密钥/值集合类

时间:2010-01-19 16:42:43

标签: java swing collections jcombobox

我有一个存储键和值的模型类:

public class KeyValue {

    private Object key;
    private String value;

    KeyValue () {
    }

    KeyValue (Object key, String value) {
        this.key=key;
        this.value=value;
    }

    public Object getKey() {
        return this.key;
    }
    public void setKey(Object key) {
        this.key=key;
    }

    public String getValue() {
        return this.value;
    }
    public void setValue(String value) {
        this.value=value;
    }

    @Override
    public String toString() {
        return this.value;
    }

}

我使用这个类来填充JComboBox的模型:

for (int i = 0; i < universes.length; i++) {
    ComboBox_Universes.addItem(new KeyValue(infoObject.ID,infoObject.title));
}

我想重构这个逻辑,使用一个可以支持两个目标的Java集合类(称之为KeyValueCollection):

1)KeyValueCollection可用于填充JComboBox的模型。类似的东西:

//get a KeyValueCollection filled with data from helper class
KeyValueCollection universeCollection = Repository.getUniverseCollection();

//use this collection as the JComboBox's model
ComboBox_Universes.setModel(universeCollection);

2)我可以使用KeyValueCollection将密钥转换为值:

//ID retrieve from another control
int universeID = (int)this.Table_Values.getModel().getValueAt(row, COLUMN_ID);

//convert ID to name
String universeName = universeCollection.get(universeID).getValue();

在.NET世界中,我会使用KeyedCollection类,但我对Java不是很熟悉。

非常感谢帮助。

6 个答案:

答案 0 :(得分:3)

你可以使用像这样的自定义类(运行main函数来查看它的行为):

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;

public class KeyValueComboboxModel extends AbstractListModel implements ComboBoxModel, Map<String, String> {

    private TreeMap<String,String> values = new TreeMap<String,String>();

    private Map.Entry<String, String> selectedItem = null;

    public Object getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(Object anItem) {
        this.selectedItem = (java.util.Map.Entry<String, String>) anItem;
        fireContentsChanged(this, -1, -1);
    }

    public Object getElementAt(int index) {
        List<Map.Entry<String, String>> list = new ArrayList<Map.Entry<String, String>>(values.entrySet());
        return list.get(index);
    }



    public int getSize() {
        return values.size();
    }

    public void clear() {
        values.clear();
    }

    public boolean containsKey(Object key) {
        return values.containsKey(key);
    }

    public boolean containsValue(Object value) {
        return values.containsValue(value);
    }

    public Set<java.util.Map.Entry<String, String>> entrySet() {
        return values.entrySet();
    }

    public String get(Object key) {
        return values.get(key);
    }

    public Set<String> keySet() {
        return values.keySet();
    }

    public String put(String key, String value) {
        return values.put(key, value);
    }

    public String remove(Object key) {
        return values.remove(key);
    }

    public int size() {
        return values.size();
    }

    public Collection<String> values() {
        return values.values();
    }

    public boolean isEmpty() {
        return values.isEmpty();
    }

    public void putAll(Map<? extends String, ? extends String> m) {
        values.putAll(m);
    }


    private static String entryToString(Map.Entry<String, String> entry) {
        String str = "" + entry.getKey() + "->" + entry.getValue();
        return str;
    }

    public static void main(String[] args) {

        Map<String,String> map= new HashMap<String,String>(){{
            put("1","blue");
            put("2","red");
            put("3","white");
            put("4","black");
        }};

        JFrame f = new JFrame();
        f.setContentPane(new JPanel(new BorderLayout()));

        KeyValueComboboxModel model = new KeyValueComboboxModel();
        model.putAll(map);

        final JComboBox combo = new JComboBox(model);
        combo.setRenderer(new DefaultListCellRenderer(){

            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index,
                    boolean isSelected, boolean cellHasFocus) {
                if(value instanceof Map.Entry){
                    Map.Entry<String,String> entry = (java.util.Map.Entry<String, String>) value;
                    String str = entryToString(entry);
                    return super.getListCellRendererComponent(list, str, index, isSelected, cellHasFocus);
                }
                return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            }

        });

        final JLabel lab = new JLabel("Nothing selected");

        combo.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e) {
                if(combo.getSelectedItem()!=null){
                    lab.setText(entryToString((java.util.Map.Entry<String, String>) combo.getSelectedItem()));
                } else {
                    lab.setText("");
                }

            }

        });

        f.getContentPane().add(combo,BorderLayout.CENTER);
        f.getContentPane().add(lab,BorderLayout.SOUTH);

        f.setSize(300,80);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null);
        f.setVisible(true);


    }


}

编辑:要处理选定的项目和键,您可以添加以下方法:

public void setSelectedKey(String key){
    selectedItem = values.ceilingEntry(key);
    setSelectedItem(key);
}

public void setSelectedItem(String key, String value){
    values.put(key, value);
    setSelectedKey(key);
}

默认情况下,值按照键的自然顺序排序(键的字母顺序,这里,因为它们是String)。如果您需要其他排序,请在java.util.Comparator中添加TreeMap(请参阅TreeMap文档)。

答案 1 :(得分:1)

Map(实现HashMap)是一个Key-Value类。

它使用方法#get。

从键转换为值

还有访问所有键,所有值等的方法。因此,用它来填充模型应该没有问题。

它还包含一个名为Map.Entry的键值对。

答案 2 :(得分:1)

java.util.Map实施怎么样?

例如,使用HashMap

,您可以:

Map<Object, String> map = new HashMap<Object, String>();
map.put(key, value);
Object value = map.get(key);

但是,您无法使用JComboBox直接填充Map。您可以将所有键添加到JComboBox,然后在需要时获取相应的值。添加可以通过多种方式完成,其中两种方式:

  • new JComboBox(map.keySet().toArray(new Object[]));
  • 循环:

    for (Object key : map.keySet() {
        comboBox.addItem(key);
    }
    

答案 3 :(得分:1)

您的第二个要求表明您需要Map,但ComboboxModelListModel,这表明您希望能够通过“索引”有效地检索元素。

我不相信任何标准集合都可以为您完成此操作,就像您想要的那样。您可以创建一个Map,然后将值复制到单独的List / ComboboxModel,也可以使用类似IndexedList的东西(一个维护索引Map的List实现)。

答案 4 :(得分:0)

我认为普通HashMap<Object,String>可以满足您的大部分需求:

// Build the map
Map<Object,String> map = new HashMap<Object,String>();
for(InfoObject io : universes) 
   map.put(io.ID,io.title);


// Populate the ComboBox
for(String s : map.values())
   ComboBox_Universes.addItem(s);


// Convert ID to name
int universeID = (int)this.Table_Values.getModel().getValueAt(row, COLUMN_ID);
String universeName = map.get(universeID);

答案 5 :(得分:0)

我使用以下代码:

/**
 * This class is slightly modified version of the Pair class from this thread:
 * http://stackoverflow.com/questions/156275/what-is-the-equivalent-of-the-c-pairl-r-in-java
 * As suggested in the thread above, I have made first & second to be final members.
 * I have made it into an Map.Entry<K,V> type, so it is suitable to be an element
 * of any Java Hash map...
 *
 * @author Dejan Lekic - http://dejan.lekic.org
 */
public class Pair<KeyT, ValueT> implements Map.Entry<KeyT, ValueT> {

    protected KeyT first;
    protected ValueT second;

    public Pair(final KeyT argFirst, final ValueT argSecond) {
        super();
        this.first = argFirst;
        this.second = argSecond;
    }

    @Override
    public int hashCode() {
        int hashFirst = (first != null) ? first.hashCode() : 0;
        int hashSecond = (second != null) ? second.hashCode() : 0;

        return (hashFirst + hashSecond) * hashSecond + hashFirst;
    }

    @Override
    public boolean equals(final Object other) {
        if (other instanceof Pair) {
            Pair otherPair = (Pair) other;
            return ((this.first == otherPair.first
                    || (this.first != null && otherPair.first != null
                    && this.first.equals(otherPair.first)))
                    && (this.second == otherPair.second
                    || (this.second != null && otherPair.second != null
                    && this.second.equals(otherPair.second))));
        } // if
        return false;
    } // equals() method

    @Override
    public String toString() {
        // previously we used " - " as a separator. Now we will use the 0x1f character, called the UNIT
        // SEPARATOR to separate two fields in a String object. See the Sise class for more information.
        return first + "\u001f" + second;
    }

    public KeyT getFirst() {
        return first;
    }

    public void setFirst(final KeyT argFirst) {
        this.first = argFirst;
    }

    public ValueT getSecond() {
        return second;
    }

    public void setSecond(final ValueT argSecond) {
        this.second = argSecond;
    }

    @Override
    public ValueT setValue(final ValueT argNewValue) {
        ValueT oldValue = second;
        second = argNewValue;
        return oldValue;
    }

    @Override
    public ValueT getValue() {
        return second;
    }

    @Override
    public KeyT getKey() {
        return first;
    }
} // Pair class

// $Id: Pair.java 149 2012-01-13 12:30:59Z dejan $