Почему removeAll() требуется в ListCellRenderer?

Это мой код:-

public class MyRender extends JPanel implements ListCellRenderer {

    ImageIcon on_img;
    JLabel name = new JLabel();
    JLabel icn = new JLabel();
    JLabel img = new JLabel();

    public MyRender(Atalk) {
        setOpaque(true);
        setBackground(Color.WHITE);
        setForeground(Color.black);
        on_img = new ImageIcon(MyCls.class.getClassLoader().getResource("imgPath"));
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        if (value != null) {
            removeAll();
            setLayout(new BorderLayout());
            User user = (User) value;
            String pres = user.getPresence().toLowerCase();
            img.setIcon(default_img);
            if (pres.contains("unavailable"))
                icn.setIcon(off_img);
            else
                icn.setIcon(on_img);
            name.setText(user.getName());
            JPanel panel = new JPanel();
            panel.setLayout(new BorderLayout());

            add(img, BorderLayout.EAST);
            add(icn, BorderLayout.WEST);

            panel.add(st, BorderLayout.CENTER);
            panel.add(name, BorderLayout.NORTH);

            add(panel, BorderLayout.CENTER);

            JLabel lbl = new JLabel(" ");
            lbl.setSize(100, 5);
            add(lbl, BorderLayout.AFTER_LAST_LINE);

            if (isSelected) {
                setBackground(Color.lightGray);
                panel.setBackground(Color.lightGray);
            } else {
                setBackground(Color.white);
                panel.setBackground(Color.white);
            }

            return this;
        }
        return null;
    }
}

Как видите, я позвонил removeAll() метод. Если я удаляю эту строку, данные не отображаются должным образом. Все данные перекрывают друг друга. И если я добавлю removeAll() все работает отлично. Почему это происходит? Нужно ли звонить removeAll()?

3 ответа

Решение

Вы должны реструктурировать свой класс так, чтобы все дети MyRender создаются и добавляются во время строительства.

getListCellRendererComponent() следует использовать ТОЛЬКО для изменения значений или визуальных атрибутов (например, фона) существующих компонентов.

Не забывай это getListCellRendererComponent() должен быть максимально быстрым (его можно вызывать довольно часто), поэтому он не должен создавать компоненты, а только модифицировать существующие.

Как правило, вот как ваш getListCellRendererComponent() метод должен выглядеть так:

@Override
public Component getListCellRendererComponent(
    JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    if (value != null) {
        User user = (User) value;
        String pres = user.getPresence().toLowerCase();
        img.setIcon(default_img);
        if (pres.contains("unavailable"))
            icn.setIcon(off_img);
        else
            icn.setIcon(on_img);
        name.setText(user.getName());
        if (isSelected) {
            setBackground(Color.lightGray);
            panel.setBackground(Color.lightGray);
        } else {
            setBackground(Color.white);
            panel.setBackground(Color.white);
        }
    }
    return this;
}

Нет, вам не нужно вызывать removeAll(). Я думаю, что ваша проблема в том, что вы создаете новый JPanel внутри метода getListCellRendererComponent каждый раз, когда вызывается метод здесь:

JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());

Если бы вы сделали этот JPanel полем класса, вам, скорее всего, не пришлось бы вызывать removeAll.

редактировать: лучше ответил jfpoilpret. 1+ для него.

Также использовать revalidate() на панели

Другие вопросы по тегам