0

How to correctly update JList after modifying its contents?

I'm building a simple Java Messageboard that looks like this:

Screen

It's a JList that has JPanels as list entries and which is displayed within a JScrollPane. In the background it is connected to a postgreSQL database. There is also a filter function that can filter messages for their author and tags.

Here is some of the code:

public Jp_Diskussion(Jp_EinProjekt thismyProject) {

    private void initiate() {
        setLayout(null);
        add(getComboBoxMa());
        add(getComboBoxTag());
        add(getLabelFiltern());
        add(getLabelOpt());
        add(getBtnBeitragVerfassen());
        initializeMessageBoard();
        // Add ItemListeners for selection of combobox entries (needed for filtering later)
        comboBoxMa.addItemListener(new ItemChangeListener());
        comboBoxTag.addItemListener(new ItemChangeListener());
    }

    public JScrollPane getScrollPane(MessageList discussionBoard) {
            messageScroll = new JScrollPane(discussionBoard);
            messageScroll.setBounds(20, 20, 954, 461);
            messageScroll.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER);

        return messageScroll;
    }

public void initializeMessageBoard() {
    // Create a custom JList (see class MessageList) called discussionBoard
    MessageList discussionBoard = new MessageList(); 

    // Get Project ID (atm still static)
    int id = 4;
    int pid = 4;

    // Get all messages and add them to ArrayList
    ArrayList <ConBeitrag> allBtr = ctBtr.getBeitraegeByProjektID(id);

    // Add all messages to the JList discussionBoard
    for (int i = 0; i < allBtr.size(); i++) {
        ConBeitrag msg = allBtr.get(i);
        discussionBoard.addMessage(msg);
    }

    // Add the ScrollPane messageScroll (which is created by getMessageScroll) with the JList as parameter to the JPanel
    this.add(getScrollPane(discussionBoard));

    // Load contents of comboboxes for the filter
    // Load all Employees
    Object[] mas = ctBtr.getAllMaByProjektId(pid).toArray();

    for (Object ma : mas) {

        this.setCbMa(ma);

    }

    // Load all tags
    Object[] tags = ctBtr.getAllTagsByProjectId(id).toArray();

    for (Object tag : tags) {
        this.setCbTag(tag);
    }
}

// ItemListener for when a selection in the comboboxes is made
public class ItemChangeListener implements ItemListener {
    public void itemStateChanged(ItemEvent event) {
        if (event.getStateChange() == ItemEvent.SELECTED) {
            filterMessages();
        }
    }
}

public void filterMessages() {

    // Get Project ID (atm still static)
    int id = 4;

    // Get selections from the comboboxes
    String ma = this.getContentCbMa().toString();
    String tag = this.getContentCbTag().toString();

    // Create new discussionBoard
    MessageList discussionBoard = new MessageList();

    // Get all messages again and put them in ArrayList btr
    ArrayList <ConBeitrag> btr = ctBtr.getBeitraegeByProjektID(id);

    // Filtering: kick all messages that don't fit filter parameters out of ArrayList btr
    if (ma != "Alle Mitarbeiter") {
        for (int i = 0; i < btr.size();) {
            ConBeitrag msg = btr.get(i);
            String msgMA = msg.getUsername();
            if (!msgMA.equals(ma)) {
                btr.remove(i);
            } else {
                i++;
            }
        }
    }

    if (tag != "Alle Schlagwörter") {
        for (int i = 0; i < btr.size();) {
            ConBeitrag msg = btr.get(i);
            ArrayList<String> msgTags = msg.getTag();               
            if (!msgTags.contains(tag)) {
                btr.remove(i);
            } else {
                i++;
            }
        }
    }

    // Add remaining messages to discussionBoard
    for (int i = 0; i < btr.size(); i++) {
        ConBeitrag msg = btr.get(i);
        discussionBoard.addMessage(msg);
    }

    // Add the ScrollPane with the JList again
    this.add(getScrollPane(discussionBoard));
            revalidate();
}

When the panel is loaded initially it displays the messages correctly. But if I filter (select an item in one of the combo boxes) the list goes blank. If I click on the blank list it shows all messages again (unfiltered). What am I doing wrong? Where do I have to repaint/revalidate?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 3
    1) For better help sooner, post an [SSCCE](http://sscce.org/). 2) A single blank line of white space in source code is *always* enough. Blank lines after `{` or before `}` are also typically redundant. 3) What is the point of the screenshot? Don't get me wrong, I'm a big fan of screenshots where appropriate, but I just don't think it adds any useful information here. 4) Typically to update a list we update the model and everything else changes automatically, BTW. – Andrew Thompson Jan 01 '14 at 16:36
  • 1
    .. 5) Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. To organize the components for a robust GUI, instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556), along with layout padding & borders for [white space](http://stackoverflow.com/q/17874717/418556). – Andrew Thompson Jan 01 '14 at 16:37
  • Right, I had to update the model, thank you. I will also look into redoing the layout with layout managers. –  Jan 01 '14 at 17:28

1 Answers1

2

Don't use a null layout and setBounds(). Swing was designed to be used with layout managers.

In the filter code you are using:

this.add(getScrollPane(discussionBoard));

Don't create new components every time you make a change. All you need to do is update the ListModel and the JList will automatically repaint itself using the model.

So the code would be something like:

DefaultListModel model = new DefaultListModel(...);

//  add items to the model

discussionBoard.setModel( model );
camickr
  • 321,443
  • 19
  • 166
  • 288