ListCellRendererComponent() method updates all the objects(elements) of JList similar to last added element

StackOverflow https://stackoverflow.com/questions/15694159

Question

hi there i implemented a JList which contains JLabels as elements. My aim is implementing a contact list for server/client chat application. So, when a client connects to a server, JList will build to show his/her contact list.I selected to use JLabels cause they can have icons and text as well. However, i'm getting some trouble about overridden cellrenderer method. Whenever, a client gets online/offline JList updates its state and set all the items similar to the last added item. It's something like this,

this is the first time adding an offline state client into the friend list of a person;

enter image description here

afterwards, this is the second time adding a different client

enter image description here

and finally third time...

enter image description here

Furthermore, i remember that in tutorial it mention about JList overrides pain method and draw whole elements again and again when there is a change in the list. Well actually i'm a newbie about this rendering subject and this thing gets very annoying. Here you can see my renderer class; RendererSample

and add an element into the model like this way in my main class

labelSetText = tempon.getNickName();
onlineStatus = tempon.isIsOnline();
model.addElement(createPanel());

and also createPanel() returns a JLabel which is like;

public static JLabel createPanel() {
    JLabel panel = new JLabel();
    return panel;
}

i hope that i have been clear about my problem. I have to achieve that when a contact changes his/her state or when a contact is added this action shouldn't affect the other elements. I will be very appreciate for every answers (and also if you can add brief explanation that what and why you did i will be grateful.) well thanks anyway

Was it helpful?

Solution

You should not put components such as JLabel into JList. Instead, use a model to hold the data and add a renderer to customize the presentation. See How to Use Lists for some examples.

Here is a very basic example of a renderer that adds icon:

import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.*;

public class TestUserList {
    public static class UserRenderer extends DefaultListCellRenderer {
        @Override
        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean hasFocus) {
            if (value instanceof UserEntry) {
                UserEntry user = (UserEntry) value;
                JLabel label = (JLabel) super.getListCellRendererComponent(
                        list, user.getName(), index, isSelected, hasFocus);
                if (user.isOnline())
                    label.setIcon(UIManager
                            .getIcon("OptionPane.informationIcon"));
                else
                    label.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
                return label;
            }
            return super.getListCellRendererComponent(list, value, index,
                    isSelected, hasFocus);
        }
    }

    public TestUserList() {
        JFrame frame = new JFrame("User List");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JList list = new JList();

        JScrollPane scrollPane = new JScrollPane(list);
        JPanel content = new JPanel(new BorderLayout());
        content.add(scrollPane, BorderLayout.CENTER);
        final DefaultListModel model = new DefaultListModel();
        model.addElement(new UserEntry("John", true));
        model.addElement(new UserEntry("Jesse", false));
        list.setModel(model);

        list.setCellRenderer(new UserRenderer());

        frame.add(content);
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

    public class UserEntry {
        private String name;
        private boolean online;

        public UserEntry(String name, boolean online) {
            super();
            this.name = name;
            this.online = online;
        }

        public String getName() {
            return name;
        }

        public Boolean isOnline() {
            return online;
        }
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestUserList();
            }
        });
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top