Java 为什么ListCellRenderer中需要removeAll()?

Java 为什么ListCellRenderer中需要removeAll()?,java,swing,listcellrenderer,Java,Swing,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);

这是我的代码:-

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?

还可以在面板上使用重新验证您必须重新构造类,以便在构建时创建并添加MyRender的所有子级

GetListCellRenderComponent应仅用于更改值或视觉属性,例如现有组件的背景

不要忘记GetListCellRenderComponent应该尽可能快,因为它可以被频繁调用,因此它不应该创建组件,而应该只修改现有的组件

通常,以下是GetListCellRenderComponent方法的外观:

@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。我认为您的问题在于每次在此处调用getListCellRenderComponent方法时,您都在该方法内部创建一个新的JPanel:

JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
如果将此JPanel设置为类字段,则可能不必调用removeAll


编辑:由jfpoilpret更好地回答。1+给他。

通常,你不需要这样。但这取决于你在JPanel里放了什么。显示更多代码可能会很有用,特别是构造函数和getListCellRenderer的其余部分。还请注意,您的方法不应返回null。@jfpoilpret:用类代码更新了我的问题。@Harry Joy。。。真的不需要,removeAll是job for Action,包括JPanel的paintBorder和ListCellRendered,默认情况下返回JLabel,现在我的问题1由JButton Action开始,您将更改JList内容,JList包含JLabel+图标+图像图标2我们谈论的是一个JList 3,但只有一个或多个JListJList@mKorbel:回答:1是Jlist包含JPanel,其中包括JLabel、ImageIcon,我稍后还会对Jlist执行操作。2总计4 Jlist,但所有共享都拥有新的MyRender。3是的。不要在@和`人名'之间使用空格,它不会通知此人。在哪里调用重新验证?最后?不,你不会明白的。我想要的是摆脱removeAll。使用removeAll可以正常工作,无需添加任何额外内容。非常好的建议,但如果您添加了一些JComponents,则只需调用revalidate,但如果您删除了一些JComponents,则需要调用revalidate+repaint,remove->add->revalidate+repaint;那么我应该在哪里对用户对象进行处理呢?我不理解你的问题;在上面的代码片段中,我没有移动任何与用户相关的内容。我所做的唯一更改是与不变组件相关的,应该在开始时创建并添加到MyRender中。很抱歉误解。没动就成功了。Thnx。