我正在使用自定义 CellRenderer 编写带有复选框的 JList,以及用于选择/取消选择、添加或删除列表元素的上下文菜单。
一切正常,我可以选择项目,打开上下文菜单并通过它删除/添加元素。我的问题是,当我添加一个元素并且列表中的元素比开始时更多时,列表消失并且我得到一个空白面板。例如,当在列表中添加一个新元素而之前没有删除一个元素时,就会发生这种情况。
为了查明问题,我一直试图将代码降到最低,但我仍然不明白为什么它不能正常工作。
我想知道的是为什么我的列表会变成空白,以及如何防止它这样做。
当然,欢迎任何旁白或建议:)
谢谢。
如果您想尝试一下,这是完整的代码(左键单击以选择项目,右键单击以打开上下文菜单):
CheckBoxList.java
package misc;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class CheckBoxList extends JList {
private int selection = -1;
protected static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public CheckBoxList(Model m) {
this();
this.setModel(m);
}
public CheckBoxList() {
this.setCellRenderer(new CheckboxCellRenderer());
this.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int index = locationToIndex(e.getPoint());
selection = index;
CheckBoxList cbl = (CheckBoxList) e.getSource();
cbl.setSelectedIndex(index);
if(index != -1) {
if(e.getButton() == MouseEvent.BUTTON1) {
Data v = (Data) getModel().getElementAt(index);
v.setSelected(!v.isSelected());
JCheckBox checkbox = new JCheckBox(v.getS(), v.isSelected());
checkbox.setSelected(!checkbox.isSelected());
repaint();
} else if(e.getButton() == MouseEvent.BUTTON3) {
ContextMenu pum = new ContextMenu(cbl);
pum.show(e.getComponent(), e.getX(), e.getY());
}
}
}
});
this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
protected class CheckboxCellRenderer implements ListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
Data v = (Data) value;
JCheckBox checkbox = new JCheckBox(v.getS(), v.isSelected());
checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground());
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder")
: noFocusBorder);
return checkbox;
}
}
public int getSelection() {
return this.selection;
}
public class ContextMenu extends JPopupMenu {
private JMenuItem deleteItem;
private JMenuItem addItem;
private CheckBoxList cbl;
public ContextMenu(CheckBoxList cbl) {
this.cbl = cbl;
this.deleteItem = new JMenuItem("Delete");
this.deleteItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem jmi = (JMenuItem) e.getSource();
ContextMenu cm = (ContextMenu) jmi.getParent();
Model m = (Model) cm.cbl.getModel();
m.remove((Data) m.getElementAt(cm.cbl.getSelection()));
cm.cbl.repaint();
}
});
this.add(deleteItem);
this.addItem = new JMenuItem("Add new");
this.addItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem jmi = (JMenuItem) e.getSource();
ContextMenu cm = (ContextMenu) jmi.getParent();
((Model) cm.cbl.getModel()).add(new Data("Added :)"));
cm.cbl.repaint();
}
});
this.add(addItem);
}
}
}
模型.java
package misc;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ListModel;
import javax.swing.event.ListDataListener;
public class Model implements ListModel {
private List<Data> data = new ArrayList<Data>();
@Override
public void addListDataListener(ListDataListener l) {}
@Override
public Object getElementAt(int index) {
return data.get(index);
}
@Override
public int getSize() {
return data.size();
}
@Override
public void removeListDataListener(ListDataListener l) {}
public void add(Data string) {
this.data.add(string);
}
public void remove(Data d) {
data.remove(d);
}
}
数据.java
package misc;
public class Data {
private String s;
private boolean selected = false;
public Data(String s) {
super();
this.s = s;
}
public String getS() {
return this.s;
}
public void setS(String s) {
this.s = s;
}
public boolean isSelected() {
return this.selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
@Override
public String toString() {
return "Data [s=" + this.s + ", isSelected=" + this.selected + "]";
}
}
主.java
package misc;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
public class Main {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setPreferredSize(new Dimension(500,200));
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Model m = new Model();
m.add(new Data("test1"));
m.add(new Data("test2"));
CheckBoxList cbl = new CheckBoxList(m);
JScrollPane jsp = new JScrollPane(cbl);
f.add(jsp);
f.pack();
f.setVisible(true);
}
}