问题
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()
?
回答1:
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;
}
回答2:
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.
回答3:
also use revalidate()
on panel
来源:https://stackoverflow.com/questions/6042955/why-removeall-is-required-in-listcellrenderer