2009-04-13 22 views
15

Ho un box a discesa nella mia GUI che mostra il contenuto di un ArrayList in un'altra classe. È possibile aggiungere nuovi oggetti a ArrayList nella GUI, quindi è necessario sapere quando viene aggiornato, quindi è possibile aggiornare il menu a discesa. Da quello che posso raccogliere, le mie due opzioni sono di estendere la classe ArrayList per permettermi di aggiungere il proprio changeListener ad esso, o di rendere osservabile la classe che contiene ArrayList in questione.Devo usare un ascoltatore o un osservatore?

Quale sarebbe una soluzione più appropriata?

+1

Si riferisce ad un JComboBox? In tal caso, esaminerei ComboBoxModel e le sue implementazioni. – Avrom

risposta

10

Le due soluzioni sono essenzialmente implementazioni dello stesso modello di progettazione radice (il modello "Observer", come definito dalla Gang of Four.) Nel primo caso, si sta rendendo "visibile" l'ArrayList, nel secondo si sta creando l'oggetto dominio che usa l'elenco di array "osservabile".

La mia tendenza sarebbe quella di fare quest'ultimo: rendere osservabile l'oggetto dominio. Questo è principalmente perché potresti eventualmente avere altre cose che potrebbero cambiare sull'oggetto dominio (per il quale la GUI dovrebbe essere aggiornata). Se è già osservabile, sei già impostato.

Nota che non è strettamente necessario estendere java.util.Observable - è possibile implementare il modello di progettazione senza farlo.

+0

Questo sembra il modo più semplice, Grazie per tutte le altre risposte però. – Simonw

9

L'implementazione di Observable in Java viene utilizzata raramente e non interagisce bene con Swing. Utilizzare invece EventListener.

In particolare, esiste un motivo per non estendere lo AbstractListModel o addirittura utilizzare DefaultListModel direttamente quando si gestisce il contenuto dell'elenco "altrove nella GUI"? Quindi la tua casella combinata potrebbe utilizzare uno ComboBoxModel che delega alla stessa istanza ListModel, aggiungendo la propria implementazione per tenere traccia dello stato di selezione.

Ho in mente qualcosa di simile (ma non sono provarlo):

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

} 
1

Preferisco sempre la composizione sull'estensione (il mio riferimento è java efficace e la mia esperienza personale). estendere ArrayList è semplicemente una promessa che non violerai nessuno degli invarianti di classi. Ti lega anche all'implementazione specifica dell'elenco che stai estendendo.

0

È possibile passare all'utilizzo di GUI design pattern. O costruire un'implementazione limitata.

creare un'interfaccia GUI modulo che ha un metodo DrawXArrayList (con X essendo un nome meaningfull Ha un parametri di tipo ArrayList

creare una nuova classe denominata GUIView Ha almeno due metodi:.. UpdateXArrayList, e RegisterForm

Quando si inizializza l'applicazione hanno la forma grafica in sé registri con la classe che implementa GUIView. Fai la classe che implementa GUIView visibile al form.

Quando qualcosa nel modulo GUI aggiorna l'arraylist l'hanno chiamata UpdateXArrayList come l'ultima cosa che fa Il metodo UpdateXArrayList nella classe che implementa GUIView a sua volta chiamerà DrawXArrayList passando l'array di aggiornamento aggiornato. DrawXArrayList nella classe form che implementa GUIFormInterface seguirà quindi i passaggi necessari per aggiornare il controllo che visualizza ArrayList.

Mentre questo sembra un sacco di passaggi rispetto a una configurazione di osservatore e ascoltatore.Hai più controllo su come le varie azioni dell'utente influenzano l'interfaccia utente, quindi il modello di osservatore-ascoltatore. Inoltre, hai documentato, nel codice, l'interazione tra l'azione dell'utente e gli aggiornamenti dell'interfaccia utente.

2

Perché non utilizzare le associazioni?

http://wiki.eclipse.org/index.php/JFace_Data_Binding

vincolare il proprio widget di GUI per la vostra lista. Le modifiche si propagheranno tra i due oggetti in modo trasparente. Assicurati di avvolgere il tuo modello con un osservabile appropriato, come WritableList (se si utilizza ArrayList direttamente).

0

Se è possibile aggiungere un nuovo vaso per l'applicazione, controlla glazed Lists