I have a dropdown box in my GUI which shows the contents of an ArrayList in another class. New objects can be added to the ArrayList elsewhere in the GUI, so I need to know when it is updated, so I can refresh the dropdown menu. From what I can gather, my two options are to extend the ArrayList class to allow me to add my own changeListener to it, or to make the class which contains the ArrayList in question extend observable.
Which would be a more appropriate solution?
The two solutions are essentially implementations of the same root design pattern (the "Observer" pattern as defined by the Gang of Four.) In the former case, you are making the ArrayList itself "observable", in the latter you are making the domain object which uses the array list "observable."
My tendency would be to do the latter: make the domain object observable. This is primarily because you may eventually have other things that could change about the domain object (for which the GUI should be updated.) If it is already observable, you're already set.
Note that you don't strictly have to extend java.util.Observable
- you can implement the design pattern without doing that.
The Observable
implementation in Java is rarely used, and doesn't inter-operate well with Swing. Use an EventListener
instead.
In particular, is there a reason not to extend AbstractListModel
or even use DefaultListModel
directly when managing the contents of the list "elsewhere in the GUI"? Then your combo box could use a ComboBoxModel
that delegates to the same ListModel
instance, adding its own implementation to track the selection state.
I have in mind something like this (but I haven't test it):
final class MyComboBoxModel
extends AbstractListModel
implements ComboBoxModel
{
private final ListModel data;
private volatile Object selection;
MyComboBoxModel(ListModel data) {
/*
* Construct this object with a reference to your list,
* which contents are managed somewhere else in the UI.
*/
this.data = data;
data.addListDataListener(new ListDataListener() {
public void contentsChanged(ListDataEvent evt) {
fireContentsChanged(this, evt.getIndex0(), evt.getIndex1());
}
public void intervalAdded(ListDataEvent evt) {
fireContentsChanged(this, evt.getIndex0(), evt.getIndex1());
}
public void intervalRemoved(ListDataEvent evt) {
fireContentsChanged(this, evt.getIndex0(), evt.getIndex1());
}
});
}
public void setSelectedItem(Object selection) {
this.selection = selection;
fireContentsChanged(this, 0, data.getSize() - 1);
}
public Object getSelectedItem() { return selection; }
public int getSize() { return data.getSize(); }
public Object getElementAt(int idx) { return data.getElementAt(idx); }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With