我有一小段代码,显示一个带有复选框列表的简单面板。行为必须如下:
如果选中了复选框“[] all”,则必须取消选中其他每个checKbox,否则(当未选中“[] all”复选框时),用户可以选择任意数量的复选框。
如果选中与“[] all”不同的复选框,则必须取消选中“[] all”复选框
从现在开始,除了如果选中“[] all”复选框之后,用户必须按两次复选框才能将其标记为已选中。第一次单击取消选中“[] all”复选框,但不选中所选复选框。我想把两种行为放在一起。我想错过一些东西(同步事件可能......)
这里的代码(自包含,如果你想要,你可以按原样运行):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class CheckListPlot extends JFrame {
public CheckListPlot() {
super("CheckList");
String[] strs = { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
JLabel label = new JLabel("Please, before to start the simulation, choose what species you desire to plot");
Font font = new Font("Tahoma", label.getFont().getStyle(), label.getFont().getSize() - 2);
label.setFont(font);
JPanel allCheckpanel = new JPanel(new BorderLayout());
allCheckpanel.setBorder(new EmptyBorder(6, 6, 6, 6));
final JCheckBox allCheck = new JCheckBox("all", false);
allCheckpanel.add(allCheck, BorderLayout.WEST);
JPanel labelPanel = new JPanel(new GridLayout(1, 1));
labelPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
labelPanel.add(label);
final JList list = new JList(createData(strs));
list.setCellRenderer(new CheckListRenderer());
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setBorder(new EmptyBorder(0, 4, 0, 0));
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int index = list.locationToIndex(e.getPoint());
CheckableItem item = (CheckableItem) list.getModel().getElementAt(index);
System.out.println("item " + item.toString() + " is selected before? " + item.isSelected());
item.setSelected(!item.isSelected());
System.out.println("item " + item.toString() + " is selected after ? " + item.isSelected());
Rectangle rect = list.getCellBounds(index, index);
list.repaint(rect);
if(allCheck.isSelected()){
allCheck.setSelected(false);
}
}
});
JScrollPane sp = new JScrollPane(list);
JButton simulateButton = new JButton("simulate");
simulateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ListModel model = list.getModel();
int n = model.getSize();
for (int i = 0; i < n; i++) {
CheckableItem item = (CheckableItem) model.getElementAt(i);
if (item.isSelected()) {
System.out.println(item.toString());
}
}
}
});
JPanel panel = new JPanel(new GridLayout(1, 1));
panel.add(simulateButton);
allCheck.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
for(int i =0 ; i< list.getModel().getSize(); i++){
((CheckableItem)list.getModel().getElementAt(i)).setSelected(false);
Rectangle rect = list.getCellBounds(i, i);
list.repaint(rect);
}
}
});
getContentPane().add(labelPanel, BorderLayout.NORTH);
getContentPane().add(allCheckpanel, BorderLayout.NORTH);
getContentPane().add(sp, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.SOUTH);
}
private CheckableItem[] createData(String[] strs) {
int n = strs.length;
CheckableItem[] items = new CheckableItem[n];
for (int i = 0; i < n; i++) {
items[i] = new CheckableItem(strs[i]);
}
return items;
}
class CheckableItem {
private String str;
private boolean isSelected;
public CheckableItem(String str) {
this.str = str;
isSelected = false;
}
public void setSelected(boolean value) {
isSelected = value;
}
public boolean isSelected() {
return isSelected;
}
public String toString() {
return str;
}
}
class CheckListRenderer extends JCheckBox implements ListCellRenderer {
public CheckListRenderer() {
setBackground(UIManager.getColor("List.textBackground"));
setForeground(UIManager.getColor("List.textForeground"));
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
setEnabled(list.isEnabled());
setSelected(((CheckableItem) value).isSelected());
setFont(list.getFont());
setText(value.toString());
return this;
}
}
public static void main(String args[]) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
CheckListPlot frame = new CheckListPlot();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 200);
frame.setVisible(true);
}
}
答案 0 :(得分:0)
更新在所有复选框中添加ItemListener的方法,如下所示
allCheck.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
for(int i =0 ; i< list.getModel().getSize(); i++){
if(e.getStateChange() == ItemEvent.SELECTED)
{
System.out.println("value"+e.getStateChange());
((CheckableItem)list.getModel().getElementAt(i)).setSelected(true);
} else
{
((CheckableItem)list.getModel().getElementAt(i)).setSelected(false);
}
Rectangle rect = list.getCellBounds(i, i);
list.repaint(rect);
}
}
});
答案 1 :(得分:0)
好的我解决了但我不知道为什么......我在这里写的解决方案是希望有人可以解释我这种奇怪的行为。我很高兴理解为什么这个小小的改变会解决所有问题。
基本上足以改变这段代码:
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// I have made the operation on the JCheckBox first of all
if(allCheck.isSelected()){
allCheck.setSelected(false);
}
int index = list.locationToIndex(e.getPoint());
CheckableItem item = (CheckableItem) list.getModel().getElementAt(index);
System.out.println("item " + item.toString() + " is selected before? " + item.isSelected());
item.setSelected(!item.isSelected());
System.out.println("item " + item.toString() + " is selected after ? " + item.isSelected());
Rectangle rect = list.getCellBounds(index, index);
list.repaint(rect);
}
});
我认为这是由于JCheckBox类和JList类之间存在一些同步问题,不是吗?似乎JCheckBox上的操作(在前面的代码中)在某些方面会导致JList丢失焦点,因此第二次单击会重置JList焦点