【问题标题】:Modifying element in DefaultListModel not updating model修改 DefaultListModel 中的元素不更新模型
【发布时间】:2013-10-31 17:40:49
【问题描述】:

我有一个JListDefaultListModel 支持,并有一个自定义CellRenderer

CellRenderer 用于在我的JList 中添加对JCheckBox 的支持。

当我尝试修改 DefaultListModel 中某个元素的选中状态时,它似乎不会更新我的 JList。当我尝试使用以下三种方法中的任何一种来获取某个索引处的元素时,就会发生这种情况:DefaultListModel.elementAt(...)DefaultListModel.get(...)DefaultListModel.getElementAt(...)

为什么我的JList 没有收到更新?

JList 部分中被注释掉的代码部分将起作用。但是,我不喜欢仅仅为了更改布尔值而将新对象复制到该位置。


这是我的代码,为了便于阅读和理解而进行了简化。


JList 部分

public AppsPanel() {
    super(new BorderLayout());

    this.appsListModel = new DefaultListModel<AppListItem>();
    this.appsList = new JList<AppListItem>(this.appsListModel);
    this.appsList.setCellRenderer(new AppsListRenderer());
    this.appsList.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            JList list = (JList) e.getSource();
            int index = list.locationToIndex(e.getPoint());

            AppListItem appListItem = (AppListItem)list.getModel().getElementAt(index);
            appListItem.setSelected(!appListItem.isSelected());

            list.repaint(list.getCellBounds(index, index));
        }
    });
    this.appsScrollPane = new JScrollPane(this.appsList);
    this.add(this.appsScrollPane);
}
...
public void selectAllApps() {
//        for (int i = 0; i < this.appsListModel.size(); i++) {
//            this.appsListModel.set(i, new AppListItem(this.appsListModel.get(i).getApp(), true));
//        }
    for (int i = 0; i < this.appsListModel.size(); i++) {
        this.appsListModel.getElementAt(i).setSelected(true);
    }
}

CellRenderer 部分。

public class AppsListRenderer extends JCheckBox implements ListCellRenderer<AppListItem> {

        @Override
        public Component getListCellRendererComponent(JList<? extends AppListItem> list, AppListItem value, int index, boolean isSelected, boolean cellHasFocus) {
            this.setSelected(value.isSelected());
            if (value.getApp() != null) {
                this.setText(value.getApp().getAppName());
            }
            return this;
        }
    }

AppListItempojo

public class AppListItem {

    private App app;

    private boolean selected;

    public AppListItem(App app, boolean selected) {
        this.app = app;
        this.selected = selected;
    }

    public App getApp() {
        return app;
    }

    public void setApp(App app) {
        this.app = app;
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }
}

Apppojo

public class App {

    private String appName;

    private String appPath;

    public App(String appName, String appPath) {
        this.appName = appName;
        this.appPath = appPath;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getAppPath() {
        return this.appPath;
    }

    public void setAppPath(String appPath) {
        this.appPath = appPath;
    }
}

【问题讨论】:

  • 请解释为什么 JCheckBox 在 non_editable JList 中呈现 JComponents
  • 默认布尔值存储在 XxxXxxModel 中,表示 JCheckBox 作为渲染 JComponents
  • 很难理解您的 cmets。 =/
  • 您的selectAllApps() 不会触发任何事件。由于您无法在默认模型上调用fire… 方法之一,因此您至少应该在更新后在JList 上调用repaint。但我建议实现你自己的模型;没那么难。
  • 扩展AbstractListModel。您只需要实现两种方法,这在委托给List 时很容易,例如ArrayListLinkedList。当然,然后添加您自己的方法。

标签: java swing jlist jcheckbox defaultlistmodel


【解决方案1】:

您的selectAllApps() 不会触发任何事件。由于您无法在默认模型上调用 fire… 方法之一,因此您至少应该在更新后在 JList 上调用 repaint

但我建议实现您自己的模型;没那么难。

public class MyListModel extends AbstractListModel<AppListItem> {

    ArrayList<AppListItem> list=new ArrayList<>();

    public void selectAllApps() {
        for(AppListItem i:list) i.setSelected(true);
        fireContentsChanged(this, 0, getSize()-1);
    }

    public int getSize() {
      return list.size();
    }

    public AppListItem getElementAt(int index) {
      return list.get(index);
    }

    // if you need such updates:
    public void add(int index, AppListItem item) {
      list.add(index, item);
      fireIntervalAdded(this, index, index);
    }

    public boolean remove(AppListItem i) {
      int index = list.indexOf(i);
      if(index<0) return false;
      remove(index);
      return true;
    }

    public void remove(int index) {
      list.remove(index);
      fireIntervalRemoved(this, index, index);
    }
}

【讨论】:

    【解决方案2】:

    在您希望将更改应用于 JList 的位置使用 AbstractListModel 的以下方法。

    fireContentsChanged (model, changeStartIndex, changeEndIndex);
    

    改变的元素由闭区间changeStartIndex、changeEndIndex指定——包含端点。

    示例: http://www.javafaq.nu/java-example-code-674.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      相关资源
      最近更新 更多