Swing MVC -刷新JComboBox已经可见的内容



我在控制器类中设置了组合框的模型

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

productCategoriesStringListModernDefaultComboBoxModel只是扩展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,我可以从AbstractTableModel实现的模型中调用fireTableRowsInserted

实际上,在AbstractListModel中有一个方法fireContentsChanged,但不像在JTable中,这个方法是受保护的,所以我不能访问它。

我知道我可以创建一个ModernDefaultComboBoxModel的实例,然后调用组合框的setModel方法来刷新组合框,但我只是想知道是否有一种"更干净"的方式像JTable一样干净

JComboBox实现ListDataListener是为了监听自己的ComboBoxModel。对DefaultComboBoxModel的任何更改都应该调用AbstractListModel中相关的fireXxxx()方法,并且JComboBox应该看到更改。只需在process()中更新combo的模型。

附录:这是一个更新模型的最小示例。在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);

最新更新