2016-10-02 7 views
0

私はユーザーが月を選択するオプションを持っています。月のリストを含むComboBoxのリスナーItemListenerを設定しました。私はユーザーが"2月"の日のリストは最大29、他の場合"4月"、 "6月"などは、私のコンボボックスで30日を持つことを選択条件を設定しています。しかし、「2月」を選択するとうまくいきますが、別の月を選択するとエラーになります。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

こんにちは! @ヘリ私はまだあなたのコードを分析して、それをすでに試しています。私はこのプロジェクトで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を有する2つの要素が除去される。

daysList.remove(removeDays[i]) 

daysListが今29要素を有しています。別の月を選択した場合は、インデックス30と一つの要素が削除された

daysList.remove(remove[i]); 

しかしdayslistだけで29個の要素を持っているので、IndexOutOfBoundsExceptionがスローされます。

したがって、itemStateChangedがトリガーされるたびにdaysListを再初期化することが1つの解決策である可能性があります。

関連する問題