カスタム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);
}
}
}
Model.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);
}
}
Data.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 + "]";
}
}
Main.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);
}
}