0

画面に2〜3個のチェックボックスフィールドを作成し、それらを垂直フィールドマネージャーに追加しています。ここでのアイデアは、別のチェックボックスをクリックして他のチェックボックスを無効にすることです。しかし、スタックオーバーフローエラーが発生しています。ここにコードを投稿しています...

final CheckboxField[] checkBoxField = new CheckboxField[2];
checkBoxField[0] = cashCardCheckboxField;
checkBoxField[1] = creditDebitCardCheckboxField;

checkBoxField[0].setChangeListener(new FieldChangeListener() {
    public void fieldChanged(Field field, int context) {

        if(context != FieldChangeListener.PROGRAMMATIC){  //It means manually clicked by User
            if(checkBoxField[0].getChecked()){
                checkBoxField[0].setChecked(false);
            }else{
                checkBoxField[0].setChecked(true);
                //Please wait Screen starts
                // call here a user defined function to populate the drop down list
                //Please wait Screen ends
            }
        }else{
            checkBoxField[0].setChecked(false);
        }
    }
});

checkBoxField[1].setChangeListener(new FieldChangeListener() {
    public void fieldChanged(Field field, int context) {

        if(context != FieldChangeListener.PROGRAMMATIC){  //It means manually clicked by User

            if(checkBoxField[1].getChecked()){
                checkBoxField[1].setChecked(false);
            }else{
                checkBoxField[1].setChecked(true);
                //Please wait Screen starts
                // call here a user defined function to populate the drop down list
                //Please wait Screen ends
            }

        }else{
            checkBoxField[1].setChecked(false);
        }

    }
});

ありがとうございます。

4

1 に答える 1

1

解決

このコードを使用してみてください。任意の数のチェックボックスを作成できます。1 つがチェックされると、リスナーは他のすべてのチェックを外します。

public class CheckBoxScreen extends MainScreen {

   private CheckboxField checkBoxField[];

   public CheckBoxScreen() {
      super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);

      checkBoxField = new CheckboxField[3];
      checkBoxField[0] = new CheckboxField("one", true);  // checked by default
      checkBoxField[1] = new CheckboxField("two", false);
      checkBoxField[2] = new CheckboxField("three", false);

      FieldChangeListener listener = new CheckboxListener();

      for (int i = 0; i < checkBoxField.length; i++) {
         checkBoxField[i].setChangeListener(listener);
         add(checkBoxField[i]);
      }
   }

   private class CheckboxListener implements FieldChangeListener {

      public void fieldChanged(Field field, int context) {

         if (context != FieldChangeListener.PROGRAMMATIC) {
            // user modified this field
            CheckboxField checkbox = (CheckboxField)field;   
            if (checkbox.getChecked()) {              
               // uncheck the other checkboxes
               for (int i = 0; i < checkBoxField.length; i++) {
                  if (checkBoxField[i] != checkbox && checkBoxField[i].getChecked()) {
                     checkBoxField[i].setChecked(false);
                  }
               }
            }
         } else {  
            // nothing more to do here ... this time, fieldChanged() is being
            //  called as a result of calling setChecked() in the code.
         }
      }      
   }
}

コードでスタック オーバーフローが発生した理由

このfieldChanged()メソッドは、フィールドのプロパティが変更されるたびに呼び出されます。のCheckboxField場合、フィールドがチェックされているかチェックされていないときに発生します。これは、ユーザーがフィールドをチェック/チェック解除するか、コードが を呼び出すために発生する可能性がありますsetChecked(boolean)。この行:

if(context != FieldChangeListener.PROGRAMMATIC){  //It means manually clicked by User

fieldChanged()ユーザーがフィールドを変更したため、またはコードによって呼び出されたために、この呼び出しが発生したかどうかを内部のコードが判断できるようにするものsetChecked()です。残念ながら、ステートメントsetChecked()のすべてのブランチに を呼び出しているため、ユーザー イベントと、コードがフィールドを変更したときの両方で が呼び出されます。 ifsetChecked()

このコードでは:

    checkBoxField[0].setChangeListener(new FieldChangeListener() {
        public void fieldChanged(Field field, int context) {

            if(context != FieldChangeListener.PROGRAMMATIC){  //It means manually clicked by User
                if(checkBoxField[0].getChecked()){
                    checkBoxField[0].setChecked(false);
                }else{
                    checkBoxField[0].setChecked(true);
                    //Please wait Screen starts
                    // call here a user defined function to populate the drop down list
                    //Please wait Screen ends
                }
            }else{
                checkBoxField[0].setChecked(false);
            }
        }
    });

checkBoxField[0].setChecked(false);問題を引き起こしているのは最後の行 ( ) です。そのブランチは、ステートメントの「手動でクリックelseされた」ブランチを呼び出した後に到達しsetChecked()ます。もう一度呼び出すと、プログラムでフィールドを変更したことになります。これにより、再度コールバックが発生します。そしてまた。そしてまた。このループは、プログラム スタックがいっぱいになり、アプリがクラッシュするまで停止しません。ifsetChecked(false)fieldChanged()

したがって、私のコードを見ると、ステートメントのプログラムブランチを呼び出しsetChecked()ていないことがわかります。コードのもう 1 つの問題は、チェックボックス 0 がチェックされているときにチェックボックス 1 をオフにする正しいロジックがないことです。しかし、それは機能上のバグにすぎません。への再帰呼び出しがスタック オーバーフローの原因です。iffieldChanged()

それが役立つことを願っています。

于 2013-09-25T01:48:41.307 に答える