为什么ListCellRenderer中需要removeAll()?

发布于 2024-11-08 04:14:15 字数 1939 浏览 0 评论 0原文

这是我的代码:-

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()

This is my code:-

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;
    }
}

As you can see I have called removeAll() method. If I remove that line the data is not displayed properly. All data overlaps each other. And If I add removeAll() all works fine. Why this happens? Is it necessary to call removeAll()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

千鲤 2024-11-15 04:14:15

您必须重构您的类,以便在构造时创建并添加 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;
}

You have to restructure your class so that all children of MyRender are created and added at construction time.

getListCellRendererComponent() should be used ONLY to change values or visual attributes (e.g. background) of existing components.

Don't forget that getListCellRendererComponent() should be as fast as possible (it can be called quite frequently), hence it should not create components but only modify existing ones.

Typically, here is how your getListCellRendererComponent() method should look like:

@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;
}
乖乖兔^ω^ 2024-11-15 04:14:15

不,您不必调用removeAll()。我认为您的问题是,每次在此处调用该方法时,您都会在 getListCellRendererComponent 方法内部创建一个新的 JPanel:

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

如果您将此 JPanel 设为类字段,则可能不必调用removeAll。

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

No, you shouldn't have to call removeAll(). I think that your problem is that you're creating a new JPanel inside of the getListCellRendererComponent method each time the method is called here:

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

If you made this JPanel a class field, you would likely not have to call removeAll.

edit: answered better by jfpoilpret. 1+ to him.

江挽川 2024-11-15 04:14:15

还可以在面板上使用revalidate()

also use revalidate() on panel

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文