2013-04-14 3 views
4

я поставил модель моего выпадающего списка в моем классе контроллераКачели MVC - обновить содержание JComboBox в то время как уже виден

cboCategory.setModel(new ModernDefaultComboBoxModel(model.getProductCategories()));

productCategories является List из String. ModernDefaultComboBoxModel - это просто модель, которая расширяет DefaultComboBoxModel.

public class ModernDefaultComboBoxModel extends DefaultComboBoxModel{ 
    public ModernDefaultComboBoxModel(List<String> elements){ 
     super(elements.toArray()); 
    } 
} 

Сейчас в моей модели, productCategories заполняется из БД, в SwingWorker

SwingWorker<Void, String> worker = new SwingWorker<Void, String>() { 
    @Override 
    protected Void doInBackground() throws Exception { 
     //query and resultset stuff 
     while (rs.next()) { 
      publish(rs.getString(1)); 
     } 
     //cleanup stuff 
    } 
    @Override protected void process(List<String> chunks){ 
     List<String> oldCategories = new ArrayList<String>(productCategories); 
     for(String cat : chunks){ 
      productCategories.add(cat); 
     } 
     fireModelPropertyChange(PRODUCT_CATEGORIES, oldCategories, productCategories); 
    } 
    @Override 
    protected void done(){ 
     //some stuff 
    } 
}; 
worker.execute(); 

в Вы видите каждый publish, он запускает событие изменения свойства его слушателя (fireModelPropertyChange это просто оболочка для firePropertyChange).

Теперь в моей модели слушателя,

@Override 
    public void propertyChange(PropertyChangeEvent evt) { 
     String propName = evt.getPropertyName(); 

     //some branching for the other models 

     else if(ProductModel.PRODUCT_CATEGORIES.equals(propName)){ 
      List<String> newVal = (List<String>)evt.getNewValue(); 

      //notify the model of the combobox that the data is changed, so refresh urself 
     } 

     //some stuff 
    } 

Я застрял в той части, где мой ModelListener должен уведомить выпадающий в представлении, что данные в его модели изменяются. У меня такая же ситуация с JTable, но с JTable Я могу просто позвонить fireTableRowsInserted из ее модели, которая реализована от AbstractTableModel.

На самом деле, в AbstractListModel существует метод fireContentsChanged, но в отличие от JTable этот метод защищен, поэтому я не могу получить к нему доступ.

Я знаю, что я могу просто создать экземпляр ModernDefaultComboBoxModel затем вызвать setModel метод выпадающий список, чтобы обновить выпадающий, но я просто интересно, если есть «чище» путь чист, как у JTable

+0

никогда-никогда не изменять лежащие в основе структуры данных о модели под ногами (и _never_ вызова любого из его методов fireXX образуют внешний код, что это врожденная ответственность самой модели) - вместо этого, использование модели апи для добавить новинки – kleopatra

+0

Ah ok. То же самое и для JTable? Нет права, потому что мы не можем добавлять данные в JTable (например, 'addItem' JComboBox) – Bnrdo

+0

@ kleopatra верен; похоже, что вы планируете регистрировать свой 'ModernDefaultComboBoxModel' в качестве слушателя в модели данных вашего приложения и правильно обновлять модель со списков; появится комбо-представление. – trashgod

ответ

2

JComboBox инвентарь ListDataListener для того, чтобы его послушать ComboBoxModel. Любое изменение вашего DefaultComboBoxModel должно вызвать соответствующий метод fireXxxx() в AbstractListModel, а JComboBox должен увидеть изменение. Просто обновите модель комбо в process().

Приложение: Вот минимальный пример, который обновляет модель. Установите точку останова на model.addElement(), отлаживайте, нажмите Добавьте и войдите в метод, чтобы увидеть вызов fireIntervalAdded(), который впоследствии обновляет представление.

JFrame f = new JFrame("ComboWorkerTest"); 
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
f.setLayout(new GridLayout(0, 1)); 
final JComboBox jcb = new JComboBox(new Integer[]{value}); 
f.add(new JButton(new AbstractAction("Add") { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     DefaultComboBoxModel model = (DefaultComboBoxModel) jcb.getModel(); 
     model.addElement(++value); 
    } 
})); 
f.add(jcb); 
f.pack(); 
f.setLocationRelativeTo(null); 
f.setVisible(true); 
+0

Но моя модель не имеет доступа к этому виду, потому что я не могу делать 'combobox.getModel'. Он может обновлять только данные моей модели combobox. Итак, как я могу это сделать? – Bnrdo

+0

Вы можете передать ссылку на модель комбо в своего работника, или ваш рабочий может запустить «PropertyChangeEvent», который будет прослушивать ваш 'ModernDefaultComboBoxModel'. – trashgod

+1

Ah ok, поэтому я могу также зарегистрировать 'ModernDefaultComboBoxModel' в качестве слушателя для моей основной модели. Спасибо. – Bnrdo