Swing MVC - refresh JComboBox contents while it is already visible

I installed my combobox model in the controller class

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

productCategories is a List of String . ModernDefaultComboBoxModel is just a model that extends DefaultComboBoxModel .

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

Now in my model productCategories populated from the database in 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(); 

You see each publish , it raises a property change event for its listener ( fireModelPropertyChange is just a wrapper for firePropertyChange ).

Now in my model listener

 @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 } 

I am stuck in the part where my ModelListener should notify the drop-down list in the view that the data in its model has changed. I have the same situation with JTable , but with JTable I can just call fireTableRowsInserted from my model, which is implemented from AbstractTableModel .

Actually, there is a fireContentsChanged method in AbstractListModel , but unlike JTable , this method is protected, so I can’t access it.

I know that I can just instantiate ModernDefaultComboBoxModel and then call the setModel method of combobox to update combobox, but I'm just wondering if the "clean" way is as clean as JTable

+4
source share
1 answer

JComboBox implements a ListDataListener to listen on its own ComboBoxModel . Any change to your DefaultComboBoxModel should call the corresponding fireXxxx() method in AbstractListModel , and the JComboBox should see the change. Just update the combo model in process() .

Appendix: Here is a minimal example that updates a model. Set a breakpoint on model.addElement() , debug, click Add and go to the method to see the fireIntervalAdded() call, which subsequently updates the view.

 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); 
+2
source

All Articles