2013-04-14 79 views
4

設置我的組合框的模式在我的控制器類搖擺MVC - 刷新JComboBox中的內容,而已經可見

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

productCategoriesString一個ListModernDefaultComboBoxModel只是延伸DefaultComboBoxModel的型號。

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

現在在我的模型,productCategories從DB填充,在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我可以從AbstractTableModel實施的模型中調用fireTableRowsInserted

實際上,在AbstractListModel中有一個方法fireContentsChanged,但與JTable不同,此方法受保護,因此我無法訪問它。

我知道我可以只創建的ModernDefaultComboBoxModel一個實例然後調用組合框的setModel方法刷新組合框,但我只是想知道是否有作爲的JTable

+0

永永遠改變模型的基礎數據結構在腳下(和_永遠_調用它的任何fireXX方法形成外部的代碼,這是模型本身所固有的責任) - 相反,使用模型API來添加新項目 – kleopatra

+0

好的。那麼JTable的情況也是如此?沒有權利,因爲我們無法將數據添加到JTable(例如JComboBox的addItem) – Bnrdo

+0

@kleopatra是正確的;看起來您正在計劃將您的'ModernDefaultComboBoxModel'註冊爲應用程序數據模型的偵聽器並正確更新組合框模型;組合視圖將隨後顯示。 – trashgod

回答

2
一個「乾淨」的方式清潔

JComboBox implements ListDataListener爲了聽自己的ComboBoxModel。對DefaultComboBoxModel的任何更改應調用AbstractListModel中的相關fireXxxx()方法,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'。它只能更新我的組合框模型的數據。那我該怎麼做? – Bnrdo

+0

您可以將對組合模型的引用傳遞給您的工作人員,或者您的工作人員可以觸發您的ModernDefaultComboBoxModel偵聽的「PropertyChangeEvent」。 – trashgod

+1

好吧,我也可以註冊'ModernDefaultComboBoxModel'作爲我的主要模型的監聽器。謝謝你。 – Bnrdo