问题
I'm trying to add a i guess you would call it a sub list to each item on a list. I've built a custom renderer that gives the below output. As you can see something isn't right here an i've had no luck tracking down an answer to my problem. I'm guessing i need to change something in the layout of the panel to get the correct result but no idea what.
http://i.stack.imgur.com/jCKjJ.jpg
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.Random;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import javax.swing.border.EmptyBorder;
public class GAListRendererAdv extends Container implements ListCellRenderer {
private static final long serialVersionUID = 1L;
private JPanel pnl = new JPanel();
private Random rnd = new Random();
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
pnl.setLayout(new BorderLayout(0, 0));
JCheckBox chckbxSomething = new JCheckBox("something");
pnl.add(chckbxSomething, BorderLayout.NORTH);
JSeparator separator = new JSeparator();
pnl.add(separator, BorderLayout.CENTER);
JPanel panel_1 = new JPanel();
panel_1.setBorder(new EmptyBorder(0, 35, 0, 0));
pnl.add(panel_1, BorderLayout.SOUTH);
panel_1.setLayout(new GridLayout(0, 1, 0, 0));
int rndNum = rnd.nextInt(5) + 1;
for (int i = 0; i < rndNum; i ++) {
JLabel lblNewLabel2 = new JLabel("New label");
panel_1.add(lblNewLabel2);
}
return pnl;
}
}
回答1:
Firstly, remember, CellRenderers
are used as "rubber stamps" in Swing. This is done to save memory and help increase performance. This allows components, like JList
, to maintain a single reference to the renderer but still paint all the items in the list.
This means, that when ever getListCellRendererComponent
is called, the renderer will be in the same state it was last it was called.
From what I can tell from your code, this will mean that each time the renderer is called, you add ANOTHER checkbox, ANOTHER separator ANOTHER panel and lots more labels...
Secondly of all, with renderers, try not to create anything in the the getListCellRendererComponent
where possible, this is just increasing you memory usage (part of your code may not have a choice).
Thirdly, JList
does not support editors, renderers are not editors, for the reasons I've stated before.
Forthly. Try removing the content from the "body" portion of the panel before adding all your elements to it.
// Don't use Container, use JPanel instead, mixing heavy and light weight components
// is never a good idea :P
public class GAListRendererAdv extends JPanel implements ListCellRenderer {
private static final long serialVersionUID = 1L;
private JPanel pnl = new JPanel();
private Random rnd = new Random();
private JCheckBox checkBox;
public GAListRendererAdv() {
setLayout(new BorderLayout(0, 0));
checkBox = new JCheckBox();
add(checkBox, BorderLayout.NORTH);
add(new JSeparator(), BorderLayout.CENTER);
pnl = new JPanel(new GridLayout(0, 1, 0, 0));
pnl.setBorder(new EmptyBorder(0, 35, 0, 0));
add(pnl BorderLayout.SOUTH); // Don't forget to add the panel :P
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
pnl.removeAll();
int rndNum = rnd.nextInt(5) + 1;
for (int i = 0; i < rndNum; i ++) {
JLabel lblNewLabel2 = new JLabel("New label");
pnl.add(lblNewLabel2);
}
return this;
}
来源:https://stackoverflow.com/questions/11751191/jlist-custom-renderer