# JComboBox updaten, ArrayList



## QDog (29. Apr 2008)

Hallo,

seitdem mein Lehrer mir vor Kurzem empfohlen hat auf ArrayLists anstatt Verctoren zu setzen, da sie performanter seien, habe ich das Problem, dass sich meine ComboBoxen nicht mehr updaten lassen.


```
// statische ArrayList
public static ArrayList<Klassen> alKlassen = new ArrayList<Klassen>();

	public static void loadKlassen() {
		List<Klassen> list = new Klassen().fetch();

		alKlassen.clear();
		for (int i = 0; i < list.size(); i++) {
			alKlassen.add((list.get(i)));
		}
	}

// im Controller
viewStammKlassen.comboBox = new JComboBox(Registry.alKlassen.toArray());

// später in einer Action
Registry.loadKlassen(); // füllt alKlassen neu
			viewStammKlassen.comboBox.validate();
			viewStammKlassen.comboBox.updateUI();
```

Sind 2 verschiedene Klassen, sollte klar sein. Die ArrayList ist laut sysout auch anders nach dem Neuladen. Nur warum updated er die GUI nicht mehr?


----------



## SlaterB (29. Apr 2008)

kannst du bitte auch den alten Code posten der was anders gemacht hat?
idealerweise in zwei ausführbaren kurzen Programmen, natürlich mit Dummy-Daten statt DB oder sonstwas


----------



## maki (29. Apr 2008)

Nutze doch lieber addAll anstatt add und iteration, Zeile 3 ist übrigens nicht schön, gar nicht.

Dein eigentliches Problem lässt sich aber nicht erkennen.


----------



## QDog (29. Apr 2008)

Dafür nun extra n Programm mit GUI ist zu viel denk ich. Das Problem scheint auf der Hand zu liegen. Wenn alKlassen wieder ein Vector ist und ich new JComboBox(Registry.alKlassen); aufrufe (ohne das .toArray() dran), geht es wunderbar. Wie schön wäre es, wenn man ArrayLists direkt in die ComboBox übergeben könnte.

@maki: Zeile3? Nicht eher Zeile 6? Was ist daran denn unschön? Was sollte ich anders machen?


----------



## maki (29. Apr 2008)

Die Referenz als List<> deklarieren anstatt ArrayList<>
public static nur für Konstanten verwenden, auf Attribute nur über getter und setter zugreifen/setzen


----------



## SlaterB (29. Apr 2008)

na dass du vorher einen Vector übergeben hast ist doch mal ne Info,

wie wärs mit folgender Erklärung:
früher benutzten dein Programm und die JComboBox ein und denselben Vector,
wenn du etwas im Vector geändert hast, dann gleichzeitig auch in der JComboBox

nun übergibst du aber der Box nicht mehr die Liste, sondern eine Kopie der Daten in einem Array,
damit hat die Box nichts mehr mit der Liste zu tun, Änderungen darin sind der JComboBox schnuppe

Lösung: entweder wieder die einfache Variante mit dem Vector
oder ein eigenes JComboBoxModel verwenden, welchem du deine Liste übergeben kannst,
ist nicht viel Aufwand

edit: nicht viel ist etwas untertrieben,
eine Klasse wie das DefaultComboBoxModel wirds wohl schon, das einfach kopieren und überall List statt Vector nehmen 


```
public class DefaultComboBoxModel extends AbstractListModel implements MutableComboBoxModel, Serializable {
    Vector objects;
    Object selectedObject;

    /**
     * Constructs an empty DefaultComboBoxModel object.
     */
    public DefaultComboBoxModel() {
        objects = new Vector();
    }

    /**
     * Constructs a DefaultComboBoxModel object initialized with
     * an array of objects.
     *
     * @param items  an array of Object objects
     */
    public DefaultComboBoxModel(final Object items[]) {
        objects = new Vector();
        objects.ensureCapacity( items.length );

        int i,c;
        for ( i=0,c=items.length;i<c;i++ )
            objects.addElement(items[i]);

        if ( getSize() > 0 ) {
            selectedObject = getElementAt( 0 );
        }
    }

    /**
     * Constructs a DefaultComboBoxModel object initialized with
     * a vector.
     *
     * @param v  a Vector object ...
     */
    public DefaultComboBoxModel(Vector<?> v) {
        objects = v;

        if ( getSize() > 0 ) {
            selectedObject = getElementAt( 0 );
        }
    }

    // implements javax.swing.ComboBoxModel
    /**
     * Set the value of the selected item. The selected item may be null.
     * 


     * @param anObject The combo box value or null for no selection.
     */
    public void setSelectedItem(Object anObject) {
        if ((selectedObject != null && !selectedObject.equals( anObject )) ||
	    selectedObject == null && anObject != null) {
	    selectedObject = anObject;
	    fireContentsChanged(this, -1, -1);
        }
    }

    // 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.elementAt(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.addElement(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.insertElementAt(anObject,index);
        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.removeElementAt(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.removeAllElements();
	    selectedObject = null;
            fireIntervalRemoved(this, firstIndex, lastIndex);
        } else {
	    selectedObject = null;
	}
    }
}
```


----------



## maki (29. Apr 2008)

Aha, Swing nutzt Vector, ein Fall in dem Vector sinnvoll ist.


----------



## Beni (29. Apr 2008)

Jeder Code, der zu einem "updateUI" führt und nichts mit dem LookAndFeel zu tun hat, ist nicht sinnvoll. :bae:

IMHO hat SlaterB mit dem ComboBoxModel schon die beste Richtung angegeben.


----------

