简体   繁体   English

在DefaultListModel中修改元素不会更新模型

[英]Modifying element in DefaultListModel not updating model

I have a JList that is supported by a DefaultListModel and has a custom CellRenderer . 我有一个DefaultListModel支持的JList ,并且有一个自定义CellRenderer

The CellRenderer is for adding support for JCheckBox in my JList . CellRenderer用于在我的JList添加对JCheckBox支持。

When i try to modify the checked state for an element in the DefaultListModel it does not appear to update my JList . 当我尝试修改DefaultListModel某个元素的选中状态时,它似乎没有更新我的JList This happens when i try to use any of the three methods to get the element at a certain index: DefaultListModel.elementAt(...) , DefaultListModel.get(...) or DefaultListModel.getElementAt(...) . 当我尝试使用三种方法中的任何一种以某个索引获取元素时,就会发生这种情况: DefaultListModel.elementAt(...)DefaultListModel.get(...)DefaultListModel.getElementAt(...)

Why is my JList not getting the update? 为什么我的JList没有得到更新?

The section of code below in my JList section that is commented out, will work. 在我的JList部分中被注释掉的下面的代码部分将起作用。 But, i do not like having to copy a new object into that position just to change the boolean. 但是,我不喜欢将新对象复制到该位置以更改布尔值。


Here is my code, simplified for easy reading and understanding. 这是我的代码,经过简化以方便阅读和理解。


JList section 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 section. 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;
        }
    }

AppListItem pojo AppListItem pojo

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

App pojo App pojo

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

Your selectAllApps() does not trigger any event. 您的selectAllApps()不会触发任何事件。 Since you can't invoke one of the fire… methods on the default model you should at least invoke repaint on the JList after the update. 由于您无法在默认模型上调用fire…方法之一,因此至少应在更新后在JList上调用repaint

But I recommend implementing your own model; 但我建议您实施自己的模型; it's not that hard. 这并不难。

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);
    }
}

Use the following method of AbstractListModel, at the point where you want the change to be applied to JList. 在要将更改应用于JList的点上,使用AbstractListModel的以下方法。

fireContentsChanged (model, changeStartIndex, changeEndIndex);

The changed elements are specified by the closed interval changeStartIndex, changeEndIndex-- the endpoints are included. 更改的元素由封闭间隔changeStartIndex,changeEndIndex指定-包括端点。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM