Search code examples
javaswingarraylistjlisteventhandler

Dynamically update JList from events


I have a JList that takes elements from an ArrayList of objects and displays some elements from the object in the list pane. When I select that element it displays the full information in other fields and labels. As part of my programme implementation I am also able to add and remove objects to the ArrayList. What I would like to do is each time the ArrayList is changed the JList will update to reflect the new state of the ArrayList. Below is the code for my JList element.

    DefaultListModel<String> defListModel = new DefaultListModel<String>();
    if(studentList.size() > 0){
        for(int i = 0; i < studentList.size(); i++){
            Student aStudent = studentList.get(i);
        defListModel.addElement(aStudent.toString());
        }
    }
    JList<String> list = new JList<String>(defListModel);
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    JScrollPane scroll = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    ListSelectionModel listSelectionModel = list.getSelectionModel();
    listSelectionModel.addListSelectionListener(new SelectionListener());
    scroll.setBounds(16, 24, 130, 205);
    mainPanel.add(scroll);

How would I go about dynamically updating this list as items are added and removed? Please do not provide a full solution (as I find I learn better by doing) but any helpful hints or suggestions where I could find a solution would be appreciated.


Solution

  • Your DefaultListModel has all the methods you need:

    void    DefaultListModel#addElement(E element);
    void    DefaultListModel#add(int index, E element);
    E       DefaultListModel#remove(int index);
    boolean DefaultListModel#removeElement(Object obj)
    

    As you add/remove items from your list, you can make the same modification to the JList's model.


    If you just make updates to your DefaultListModel, you can recover your ArrayList with:

    studentList = Collections.list(defListModel.elements());  // creates new ArrayList
    

    or, if other references to studentList must be maintained:

    studentList.clear();
    studentList.addAll(Collections.list(defListModel.elements()));
    

    EDIT Whoops! Sorry. Your ArrayList<?> studentList is of a unknown unspecified type ; we can't recover the original list. Even the ArrayList<String> of student names cannot be reliably matched back to individual students, since #toString() may return a different String each time it is called, depending on how it is implemented, and student names may not be unique. You'll just have to do the same operations to both lists.


    EDIT The default renderer for a JList will call #toString() on the objects in the list. Instead of calling defListModel.addElement(aStudent.toString()), you could add the actual objects to the appropriately typed JList/DefaultListModel.

    DefaultListModel<Student> defListModel = new DefaultListModel<>();
    // ...
        defListModel.addElement(aStudent);
    // ...
    JList<Student> list = new JList<>(defListModel);
    

    With this change, the defListModel can be modified, and the corresponding changes to the student list can be recovered with:

    studentList = Collections.list(defListModel.elements());