动态添加和删除复选框

时间:2018-06-16 09:20:36

标签: java swing checkbox

我想制作ToDoList App。成功添加要执行的任务(其中包含复选框,JLabel和日期,所有都放在一个框中)后我想动态删除它们。添加它不是问题,但当我尝试删除(在复选框中单击已选中)时,它只能运行一次。然后它要么不删除一次,要么根本不删除它们。我不确定为什么它不起作用所以我粘贴下面的所有代码。

JSpinner dateSpin;
Box eventBox, boxBox;
Box[] taskBox = new Box[1000];
JTextField eventName;
Date date;
Checkbox[] doneCheck = new Checkbox[1000];
JLabel taskLabel;
JPanel panel;
JScrollPane scrollPane;
SimpleDateFormat simpleDate;
int i = 0;

public static void main(String[] args) {

    new Main();
}

private Main(){
    this.setSize(400, 600);
    this.setTitle("To-Do List");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.setLocationRelativeTo(null);


    panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    boxBox = Box.createVerticalBox();
    scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    eventBox = Box.createHorizontalBox();
    eventBox.setBorder(BorderFactory.createEtchedBorder());

    JLabel plusSign = new JLabel("+");
    plusSign.setFont(new Font("Serafi", PLAIN, 20));
    plusSign.setMaximumSize(new Dimension(Integer.MAX_VALUE, plusSign.getMinimumSize().height));
    eventBox.add(plusSign);

    eventName = new JTextField(20);
    eventName.setFont(new Font("Times", Font.ITALIC, 15));
    eventName.setMaximumSize(new Dimension(Integer.MAX_VALUE, eventName.getMinimumSize().height));
    eventName.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == eventName){
                /* to do: saving every task in some file, figure out how to remove
                   those tasks (checkbox + jlabel) -> whole box from screen or how to send them to "done"
                   also "done" to do*/



                simpleDate = new SimpleDateFormat("E-dd-MM-yyyy");
                taskBox[i] = Box.createHorizontalBox();
                taskBox[i].setBorder(BorderFactory.createTitledBorder(simpleDate.format(date)));


                doneCheck[i] = new Checkbox();
                doneCheck[i].addItemListener(new ItemListener() {
                    @Override
                    public void itemStateChanged(ItemEvent e) {

                        int k = 0;
                        for (int j = 0; j < doneCheck.length; j++) {
                            if(doneCheck[j].getState()){
                                //remove(doneCheck[k]);
                                //System.out.println("?" + i + "?" + k + " " + e.getSource().toString());
                                System.out.println("xxxxx" + doneCheck[j].getState());
                                break;
                            }
                            System.out.println("oooooo");
                            k++;

                        }
                        System.out.println(doneCheck.length + taskBox[k].toString());
                        //System.out.println("! " + k +  " " + e.getSource().toString());
                        boxBox.remove(taskBox[k]);
                        //boxBox.removeAll();
                        boxBox.revalidate();
                        boxBox.repaint();

                    }
                });

                taskBox[i].add(doneCheck[i]);

                String taskName = eventName.getText();
                taskLabel = new JLabel(taskName);
                taskLabel.setMinimumSize(new Dimension(500,10));
                taskLabel.setPreferredSize(new Dimension(300, 10));
                taskBox[i].add(taskLabel);

                boxBox.add(taskBox[i]);
                boxBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, boxBox.getMinimumSize().height + 11));
                panel.add(boxBox);
                panel.revalidate();
                panel.repaint();
                i++;
            }
        }
    });
    eventBox.add(eventName);

    date = new Date();
    dateSpin = new JSpinner(new SpinnerDateModel(date, null, null, Calendar.DAY_OF_MONTH));
    JSpinner.DateEditor dateEditor = new JSpinner.DateEditor(dateSpin, "dd/MM/yy");
    dateSpin.setEditor(dateEditor);
    dateSpin.setMaximumSize(new Dimension(Integer.MAX_VALUE, dateSpin.getMinimumSize().height));
    dateSpin.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            if(e.getSource() == dateSpin){
                date = (Date) dateSpin.getValue();

            }
        }
    });
    eventBox.add(dateSpin);

    panel.add(eventBox, new FlowLayout());

    this.add(scrollPane);
    this.setVisible(true);
}

3 个答案:

答案 0 :(得分:0)

除非您在某处初始化doneCheck项目,否则:

Checkbox[] doneCheck = new Checkbox[1000];

而且:

int k = 0;
for (int j = 0; j < doneCheck.length; j++) {
    if (doneCheck[j].getState()) {
--------^^^^^^^^^^^^

可能是失败的原因之一:你可能在某处有一个NullPointerException,例如:j > 0的值。 NPE可能会被EventDispatchThread捕获,它可能或者可能不足以在stderr上显示它......

我不明白你为什么要使用这个数组,你可以缩短代码并避免像这样的NPE:

Checkbox cb = new Checkbox();
cb.addItemListener(event -> {
  if (cb.getState()) { // not null!
    boxBox.remove(cb);
    boxBox.revalidate();
    boxBox.repaint();
  }
});

doneCheck[i] = cb; // I still don't know why you need that.

答案 1 :(得分:0)

您永远不会从taskBoxdoneCheck数组中删除元素。

现在,如果您将第一个条目标记为已完成,则ItemListener将在循环遍历doneCheck数组时始终找到第一个条目。

将条目标记为按相反顺序完成(始终是最后显示的条目)将删除一个条目后的另一个条目。

关于您的软件设计:在多个并行阵列中管理数据被认为是不好的做法。

请考虑为管理单个待办事项的所有元素的待办事项创建自定义类。

答案 2 :(得分:0)

我的猜测是,您在这里有2个变量全局int i = 0和本地int k = 0

           public void itemStateChanged(ItemEvent e) {

                   // int k = 0;//<-------- LOCAL
                    for (int j = 0; j < doneCheck.length; j++) {
                        if(doneCheck[j].getState()){
                         //Either k = j;
                            boxBox.remove(taskBox[j]);                  
                            //remove(doneCheck[k]);
                            //System.out.println("?" + i + "?" + k + " " +      e.getSource().toString());
                            System.out.println("xxxxx" + doneCheck[j].getState());
                            break;
                        }
                        System.out.println("oooooo");
                        //k++;//<-- ALWAYS == last j value before the break;

                    }
                    System.out.println(doneCheck.length + taskBox[k].toString());
                    //System.out.println("! " + k +  " " + e.getSource().toString());
                    //boxBox.remove(taskBox[k]);//
                    //boxBox.removeAll();
                    boxBox.revalidate();
                    boxBox.repaint();

                }

每次调用itemStateChanged int k = 0;时都会初始化为0,您将从taskBox数组中删除元素[j]。因为你的k ++语句将等于break之前的最后一个j值;因为它位于if(doneCheck[j].getState()){...之后 尝试在for循环中移动boxBox.remove(taskBox[j]);并使用j代替k。