【问题标题】:Why removeAll() is required in ListCellRenderer?为什么 ListCellRenderer 中需要 removeAll()?
【发布时间】:2011-08-27 22:17:58
【问题描述】:

这是我的代码:-

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

【问题讨论】:

  • 通常情况下,你不需要那个。但这取决于您在 JPanel 中放入的内容。显示更多代码可能很有用,尤其是构造函数和 getListCellRenderer 的其余部分。
  • 另请注意,您的方法永远不应返回 null。
  • @jfpoilpret:用类代码更新了我的问题。
  • @ Harry Joy ... 真的不要,removeAll() 是 Action 的工作(包括 JPanel 的paintBorder)和 ListCellRendered 默认返回 JLabel,现在我的问题 1)由 JButton Action 你' d 更改 JList 内容并且 JList 包含 JLabel + Icon + ImageIcon 2)只有一个 JList 或多个 JList 3)我们在谈论 JList
  • @mKorbel: Answers:1) 是的,Jlist 包含 JPanel,其中包括 JLabel、ImageIcon,我稍后还会对 JList 执行操作。 2) 共有 4 个 Jlist,但所有共享都拥有 new MyRender()。 3) 是的。不要在@ 和`人名`之间使用空格,它不会通知那个人。

标签: java swing listcellrenderer


【解决方案1】:

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

【讨论】:

  • 那我应该在哪里处理User对象呢?
  • 我不明白你的问题;在我上面的 sn-p 中,我没有移动任何与用户相关的内容。我所做的唯一更改与不变组件有关,应该在开始时创建并添加到 MyRender 中。
  • 抱歉造成误会。没有removeAll()就可以了。谢谢。
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

    在面板上也使用revalidate()

    【讨论】:

    • 在哪里打电话给revalidate()?最后?
    • 不,你没有得到我。我想要的是摆脱removeAll()。使用removeAll() 一切正常,无需添加任何额外内容。
    • 非常好的建议,但是如果你添加一些JComponents然后调用revalidate(),但是如果你删除了一些JComponents,那么你需要调用revalidate()加上repaint(),remove -> add -> 重新验证() + 重新绘制();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    • 2019-06-09
    • 2012-07-26
    • 2020-03-22
    • 2011-08-11
    • 2019-06-09
    • 2012-05-21
    相关资源
    最近更新 更多