为什么JComboBox不会从自定义模型中显示字符串?

时间:2021-11-07 12:39:45

I created a custom model for JCombobox to synchronize it with a LinkedHashMap. I wanted to create a model that could be reused with any LinkedHashMap (hence the use of generics). When I run it with my application, the String fail to appear. When I click on where the Strings should be, the action listeners fire correctly and the selected item changes. Nevertheless, the dropdown menu does not display the String? I know it's based of a JList so do I need to do anything fancy with JLabels and such? Is that part of the model as well? Do I need to implement anything else?

我为JCombobox创建了一个自定义模型,以便将它与LinkedHashMap同步。我想创建一个可以与任何LinkedHashMap重用的模型(因此使用泛型)。当我使用我的应用程序运行它时,String无法显示。当我单击字符串应该在哪里时,动作侦听器会正确触发并且所选项目会更改。然而,下拉菜单不显示字符串?我知道它基于JList,所以我需要做任何与JLabel有关的事情吗?这也是模型的一部分吗?我还需要实施其他任何措施吗?

Here is my custom model

这是我的自定义模型

import java.io.Serializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

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

/**
 * A model design to automatically update based of a the key values of a Hashmap
 * @author Skylion
 *
 * @param <K> The generic representing key of the Hashmap
 * @param <V> The generic representing the value of the Hashmap
 */
public class HashMapComboBoxModel<K, V> extends AbstractListModel<K> implements MutableComboBoxModel<K>, 
Serializable {

    /**
     * Auto-generated
     */
    private static final long serialVersionUID = -1293826656458176439L;

    /**
     * The Selected Item
     */
    private K selectedItem;

    LinkedHashMap<K,V> data;

    public HashMapComboBoxModel(LinkedHashMap<K,V> data){
        this.data = data;
    }

    @Override
    public K getElementAt(int index) {
        List<Entry<K,V>> randAccess = new ArrayList<Entry<K,V>>((Collection<? extends Entry<K, V>>) data.entrySet());
        return randAccess.get(index).getKey();
    }

    @Override
    public int getSize() {
        return data.size();
    }

    @Override
    public K getSelectedItem() {
        return selectedItem;
    }

    @SuppressWarnings("unchecked")//Equals() implements the check
    @Override
    public void setSelectedItem(Object anItem) {
        for(K keys: data.keySet()){
            if(keys.equals(anItem)){
                this.selectedItem = (K) anItem;
                return;
            }
        }
    }

    @Override
    public void addElement(Object obj) {
            addElement(downcastToEntry(obj));
    }

    @SuppressWarnings("unchecked")
    private Entry<K,V> downcastToEntry(Object obj){
        if(obj instanceof Entry && obj.getClass().isAssignableFrom(
                data.entrySet().iterator().next().getClass())){
            return (Entry<K,V>)obj;
        }
        return null;
    }

    /**
     * Adds an Entry value to the hashmap
     * @param obj The Entry value you want to add
     * @return return true if added false otherwise
     */
    public boolean addElement(Entry<K,V> obj){
        if(obj == null){return false;}
        return this.data.entrySet().add(obj);
    }

    @Override
    public void insertElementAt(Object obj, int index) {
        Entry<K,V> entry = downcastToEntry(obj);
        addToMapAtIndex(index, entry.getKey(), entry.getValue());
    }

    private void addToMapAtIndex(int index, K key, V value) {
        assert (data != null);
        assert !data.containsKey(key);
        assert (index >= 0) && (index < data.size());

        int i = 0;
        List<Entry<K, V>> rest = new ArrayList<Entry<K, V>>();
        for (Entry<K, V> entry : data.entrySet()) {
            if (i++ >= index) {
                rest.add(entry);
            }
        }
        data.put(key, value);
        for (int j = 0; j < rest.size(); j++) {
            Entry<K, V> entry = rest.get(j);
            data.remove(entry.getKey());
            data.put(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public void removeElement(Object obj) {
        data.remove(obj);
    }

    @Override
    public void removeElementAt(int index) {
        data.remove(getElementAt(index));
    }

}

Here is how I constructed the JCombobox.

这就是我构建JCombobox的方法。

LinkedHashMap<String, myCustomClass> map = new LinkedHashMap<String, myCustomClass(); // CODE... CODE... more code...

LinkedHashMap map = new LinkedHashMap ,mycustomclass();> ,mycustomclass>

JCombobox box = new JCombobox<String>(new HashMapComboBoxModel<String,myCustomClass>(map));

JCombobox box = new JCombobox (new HashMapComboBoxModel (map)); ,mycustomclass>

//Later in the code

//稍后在代码中

map.put("myString", myObject); //JCombobox updates, but the dropdown is whited out.

map.put(“myString”,myObject); // JCombobox更新,但下拉列表被删除了。

1 个解决方案

#1


0  

NVM, I figured it out. I need to call the fire the DataListener method. After looking at the source code for JCombobox, I need to use the add methods through the model for it to properly update. Instead of rewriting the class, I decided to simply fire the listeners on the getSize() method as a little hack. I force the entire list to update when the method is called so that when the combobox executes the for loop, it automatically updates the model.

NVM,我想通了。我需要调用fireListener方法。在查看JCombobox的源代码之后,我需要通过模型使用add方法来正确更新。我没有重写这个类,而是决定简单地将getSize()方法上的监听器作为一个小黑客来触发。我强制整个列表在调用方法时更新,以便当组合框执行for循环时,它会自动更新模型。

It maybe hacky but it works!

它可能是hacky但它​​的工作原理!

#1


0  

NVM, I figured it out. I need to call the fire the DataListener method. After looking at the source code for JCombobox, I need to use the add methods through the model for it to properly update. Instead of rewriting the class, I decided to simply fire the listeners on the getSize() method as a little hack. I force the entire list to update when the method is called so that when the combobox executes the for loop, it automatically updates the model.

NVM,我想通了。我需要调用fireListener方法。在查看JCombobox的源代码之后,我需要通过模型使用add方法来正确更新。我没有重写这个类,而是决定简单地将getSize()方法上的监听器作为一个小黑客来触发。我强制整个列表在调用方法时更新,以便当组合框执行for循环时,它会自动更新模型。

It maybe hacky but it works!

它可能是hacky但它​​的工作原理!