2016-10-02 67 views
0

我有一个用户选择一个月的选项。我为我的ComboBox设置了一个监听器ItemListener,它包含几个月的列表。我有一个设置条件,如果用户选择“二月”天的列表将只能达到29 else “四月”,“六月”等将有30天在我的组合框。但是,当我选择“二月”它工作正常,但当我选择另一个月,我得到一个错误。使用ArrayList的IndexOutOfBoundsException

IndexOutOfBoundsException: Index: 30, Size: 29

我知道这个错误发生,因为再过一个月有30一个指标,我有点迷惑我应该删除的ArrayList或组合框的内容?任何帮助我如何消除这种情况?

private ItemHandler handler = new ItemHandler(); 

ArrayList<String> daysList = new ArrayList<String>(); 

String[] daysObj = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", 
     "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"}; 
DefaultComboBoxModel daysModel = new DefaultComboBoxModel(daysObj); 

public AddEmployee() 
{ 
    setMonths(); 
    setDays(); 
    cbMonths.addItemListener(handler); 
} 

private void setDays() 
{ 
    for(int i = 0; i < daysObj.length; i++) 
    { 
     daysList.add(daysObj[i]); 
    } 

    cbDays.setModel((ComboBoxModel)daysModel); 
} 

private class ItemHandler implements ItemListener 
{ 
    int removeDays[] = {29,30};//array 
    int remove[] = {30}; 
    @Override 
    public void itemStateChanged(ItemEvent e) 
    { 
     if(e.getSource() == cbMonths)//Check where combobox occured. 
     { 
      if(cbMonths.getSelectedItem().equals("February")) 
      { 
       for(int i = removeDays.length-1; i >= 0; i--) 
       { 
        daysList.remove(removeDays[i]);//Remove given array from ArrayList using removeDays[] 
        System.out.println("NEW ELEMENT: "+daysList); 
       } 

       for(String s : daysList)//Update ArrayList 
       { 
        cbDays.addItem(s); 
        System.out.println("NEW LIST OF ARRAY: "+s); 
       } 

      } 
      else if(cbMonths.getSelectedItem().equals("April") || cbMonths.getSelectedItem().equals("June") || 
        cbMonths.getSelectedItem().equals("September") || cbMonths.getSelectedItem().equals("November")) 
      { 
       for(int i = remove.length-1; i >= 0; i--) 
       { 
        daysList.remove(remove[i]); 
        System.out.println(daysList); 
       } 

       for(String a : daysList)//Update ArrayList 
       { 
        cbDays.addItem(a); 
        System.out.println("NEW LIST OF ARRAY: "+a); 
       } 

      } 
     } 
} 

我试过方法removeAllItems(),但它看起来很喜欢它不起作用。 cbDays.removeAllItems();

回答

1

而不是每次用户选择另一个月(这是很难阅读和容易出错)进行复杂的计算,更好地初始化一些覆盖所有情况的静态模型。您的StateChaged处理程序然后只需选择正确的模型。下面的例子是基于新奇特的Java 8日期时间API:

private static String[] initDays(int number) 
{ 
    String[] result = new String[ number]; 

    for (int i = 0; i < result.length; i++) 
    { 
     result[i] = "" + (i+1); 
    } 

    return result; 
} 

private static final String[] days28 = initDays(28); 
private static final String[] days29 = initDays(29); 
private static final String[] days30 = initDays(30); 
private static final String[] days31 = initDays(31); 

private static final ComboBoxModel<String> model28 = new DefaultComboBoxModel<>(days28); 
private static final ComboBoxModel<String> model29 = new DefaultComboBoxModel<>(days29); 
private static final ComboBoxModel<String> model30 = new DefaultComboBoxModel<>(days30); 
private static final ComboBoxModel<String> model31 = new DefaultComboBoxModel<>(days31); 

private static final Set<Month> month30 = EnumSet.of(
     Month.FEBRUARY, 
     Month.APRIL, 
     Month.JUNE, 
     Month.SEPTEMBER, 
     Month.NOVEMBER 
    ); 
private static final Set<Month> month31 = EnumSet.of(
     Month.JANUARY, 
     Month.MARCH, 
     Month.MAY, 
     Month.JULY, 
     Month.AUGUST, 
     Month.OCTOBER, 
     Month.DECEMBER 
    ); 
private JComboBox<String> cbMonths = new JComboBox<>(); 
private JComboBox<String> cbDays = new JComboBox<>(); 

public void itemStateChanged(ItemEvent e) 
{ 
    if(e.getSource() == cbMonths)//Check where combobox occured. 
    { 
     if(cbMonths.getSelectedItem().equals("February")) 
     { 
      Month selectedMonth = Month.valueOf(cbMonths.getItemAt(cbMonths.getSelectedIndex())); 

      if (month31.contains(selectedMonth)) 
      { 
       cbDays.setModel(model31); 
      } 
      else if (month30.contains(selectedMonth)) 
      { 
       cbDays.setModel(model30); 
      } 
      else 
      { 
       if (Year.isLeap(Instant.now().getLong(ChronoField.YEAR))) 
       { 
        cbDays.setModel(model29); 
       } 
       else 
       { 
        cbDays.setModel(model28); 
       } 
      } 
     } 
    } 
} 

进一步的增强可能是使用的是直接由每月枚举类型的一个cbMonth,并提供显示当月的区域单元格渲染的用户。

+0

嗨! @Heri我仍然在分析你的代码并且已经尝试过了。我在这个项目上使用了GUI Builder。我仍然应该调用'private JComboBox cbMonths = new JComboBox <>();'?因为cbMonths和cbDays已经定义:D。另外我有点混淆在构造函数中调用'initDays()'。它应该与课堂上的对象串联起来吗? 'myObject.initDays();'? –

+0

我初始化cbMonths和cbDays的行只在我的eclipse中用于编译(并且我已经将它整体复制到这里)。如果您已经有了初始化实例,请使用这些实例。 – Heri

+0

initDays不在构造函数中调用。它是静态的,只被调用一次:当类由JVM的类加载器加载时。 – Heri

0

初始化后通过setDays()daysList包含31个元素。当选择February,指数2930两个元件移除:

daysList.remove(removeDays[i]) 

daysList现在具有29元件。当选择再过一个月,与索引30一个元素被删除

daysList.remove(remove[i]); 

但是dayslist只有29组的元素,所以一个IndexOutOfBoundsException被抛出。

因此,一种解决方案可能是每次触发itemStateChanged时重新初始化daysList

相关问题