Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JList需要单击两次以更新CheckableItem_Java_Swing_Jlist_Jcheckbox - Fatal编程技术网

Java JList需要单击两次以更新CheckableItem

Java JList需要单击两次以更新CheckableItem,java,swing,jlist,jcheckbox,Java,Swing,Jlist,Jcheckbox,我有一小段代码,它显示了一个简单的面板,其中有一个复选框列表。行为必须如下所示: 如果选中了复选框[]all,则必须取消选中其他复选框,否则当未选中[]all复选框时,用户可以选择任意数量的复选框 如果选中了与[]all不同的复选框,则必须取消选中[]all复选框 现在还没有什么奇怪的,只是如果选中了复选框[]all,那么用户必须相互按下两次复选框才能将其标记为选中。第一次单击取消选中[]全部复选框,但不选中选中的复选框。我想把这两种行为结合起来。我猜错过了什么同步活动可能 这里的代码是自包含的

我有一小段代码,它显示了一个简单的面板,其中有一个复选框列表。行为必须如下所示:

如果选中了复选框[]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);
}
}

更新在所有复选框上添加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);
        }
    }
});

好的,我解决了,但我不知道为什么。。。我在这里写下解决方案,希望有人能解释我这种奇怪的行为。我很乐意理解为什么这个小小的改变可以解决一切

基本上,更改这段代码就足够了:

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焦点

阅读答案,它对您的问题提出了建议。感谢您的回复;是一个很好的选择。谢谢您的回复,但是当我按[]all时,您的代码会标记其他复选框。正如上面所读到的,这不是预期的行为