从按钮阵列修改按钮

问题描述:

我正在尝试编写一个程序,以便每当按下名为'front'的按钮时,除了等于GreenButton的按钮外,其他所有按钮都将变为灰色。我正在努力访问for循环中的按钮,并不断得到空指针异常。从按钮阵列修改按钮

完整的logcat如下图所示,这表明NPE是,当我试图访问数组中的循环发生

09-20 11:50:54.727 5302-5302/com.example.kshah.movingbutton E/AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.example.kshah.movingbutton, PID: 5302 
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setBackgroundColor(int)' on a null object reference 
     at com.example.kshah.movingbutton.MainActivity$1.onTouch(MainActivity.java:108) 
     at android.view.View.dispatchTouchEvent(View.java:9296) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403) 
     at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737) 
     at android.app.Activity.dispatchTouchEvent(Activity.java:2771) 
     at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) 
     at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364) 
     at android.view.View.dispatchPointerEvent(View.java:9520) 
     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230) 
     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787) 
     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) 
     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922) 
     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896) 
     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857) 
     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025) 
     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) 
     at android.os.MessageQueue.nativePollOnce(Native Method) 
     at android.os.MessageQueue.next(MessageQueue.java:323) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5417) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

CODE:

public class MainActivity extends AppCompatActivity { 

    private Button front; 
    private Button a; 
    private Button b1; 
    private Button b2; 
    private Button b3; 
    private Button b4; 

    Button[] buttons = {front,a,b1,b2,b3,b4}; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    front = (Button) findViewById(R.id.front); 
    a = (Button) findViewById(R.id.a); 
    b1 = (Button) findViewById(R.id.b1); 
    b2 = (Button) findViewById(R.id.b2); 
    b3 = (Button) findViewById(R.id.b3); 
    b4 = (Button) findViewById(R.id.b4); 

    front.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent event) { 
       Button GreenButton = b3; 
      for(int i = 0; i <= buttons.length; i++) { 
       if (buttons[i] == b3) { 
        buttons[i].setBackgroundColor(Color.GREEN); 
       } 
       else 
        buttons[i].setBackgroundColor(Color.GRAY); 
      } 
      return false; 
     } 
    }); 
    } 
} 
+0

发布错误的完整logcat。不要修改或修剪 –

+0

使用'for(int i = 0; i

+0

@Pavneet_Singh仍然导致上述错误中显示的空指针异常 –

您可以尝试使用新的按钮【尺寸】,像这样:

// allocates memory for 6 button. 
Button[] buttons = new Button[6]; 

然后,添加按钮将其:

front = (Button) findViewById(R.id.front); 
a = (Button) findViewById(R.id.a); 
b1 = (Button) findViewById(R.id.b1); 
b2 = (Button) findViewById(R.id.b2); 
b3 = (Button) findViewById(R.id.b3); 
b4 = (Button) findViewById(R.id.b4); 

buttons[0] = front; 
buttons[1] = a; 
buttons[2] = b1; 
buttons[3] = b2; 
buttons[4] = b3; 
buttons[5] = b4; 

说明

当你创建阵列:

private Button front; 
private Button a; 
private Button b1; 
private Button b2; 
private Button b3; 
private Button b4; 

Button[] buttons = {front,a,b1,b2,b3,b4}; 

你创建与空对象的数组,这就好比

Button[] buttons = {null,null,null,null,null,null}; 

然后,当你的按钮分配给数组成员与之一:

front = (Button) findViewById(R.id.front); 

你分配一个对象frontbuttons[0]


你可以试试下面的代码来理解上述说明的意思:

public class MainActivity extends AppCompatActivity { 
    public static final String TAG = MainActivity.class.getSimpleName(); 

    private Button front; 
    private Button a; 
    private Button b1; 
    private Button b2; 
    private Button b3; 
    private Button b4; 

    Button[] buttons = {front,a,b1,b2,b3,b4}; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // Check address: 
    Log.d(TAG, "Before initializing.."); 
    for(int i = 0; i < buttons.length; i++) { 
     Log.d(TAG, "i " + buttons[i]); 
    } 
    front = (Button) findViewById(R.id.front); 
    a = (Button) findViewById(R.id.a); 
    b1 = (Button) findViewById(R.id.b1); 
    b2 = (Button) findViewById(R.id.b2); 
    b3 = (Button) findViewById(R.id.b3); 
    b4 = (Button) findViewById(R.id.b4); 
    Log.d(TAG, "After initializing.."); 
    for(int i = 0; i < buttons.length; i++) { 
     Log.d(TAG, "i " + buttons[i]); 
    } 

    Log.d(TAG, "After assigning.."); 
    Log.d(TAG, "front " + front); 
    Log.d(TAG, "a " + a); 
    Log.d(TAG, "b1 " + b1); 
    Log.d(TAG, "b2 " + b2); 
    Log.d(TAG, "b3 " + b3); 
    Log.d(TAG, "b4 " + b4); 

    } 
} 

不能存储在引用像这样的初始化器阵列

Button[] buttons = {front,a,b1,b2,b3,b4}; 

但是为什么?放手Array Initializers

数组的长度,以构成等于立即由阵列 初始化的括在大括号 变量初始值设定的数量。空间被分配给这个长度的新数组。如果 没有足够的空间来分配数组,则通过抛出OutOfMemoryError突发性地完成对数组初始值设定项的评估。 否则,a one-dimensional array is created of the specified lengthand each component of the array is initialized to its default value

所以这里的引用将只由值替换意味着null因此他们不能再保持变化的轨迹在实际的参考值

所以解决的办法是根据要求的长度声明arrayArrayList并添加对它的引用。

//     {null,null,null,....} 
//Button[] buttons = {front,a,b1,b2,b3,b4}; 
    Button[] buttons = new Button[6]; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    buttons[0] = (Button) findViewById(R.id.front); 
    buttons[1] = (Button) findViewById(R.id.a); 
    buttons[2] = (Button) findViewById(R.id.b1); 
    buttons[3] = (Button) findViewById(R.id.b2); 
    buttons[4] = (Button) findViewById(R.id.b3); 
    buttons[5] = (Button) findViewById(R.id.b4); 

    buttons[0].setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent event) { 
       Button GreenButton = b3; 
      // note < instead of <= 
      for(int i = 0; i < buttons.length; i++) { 
       if (buttons[i] == buttons[4]) { 
        buttons[i].setBackgroundColor(Color.GREEN); 
       } 
       else 
        buttons[i].setBackgroundColor(Color.GRAY); 
      } 
      return false; 
     } 
    }); 

for(int i = 0; i <= buttons.length; i++){do something with buttons[i]}从来都不是一个有效的“for”循环的原因很简单。它总是会给你NullPointerException,因为在循环的最后一个循环中,当我== buttons.length();你正试图对按钮[buttons.length()]执行一个简单不存在的操作。

尝试for(int i = 0; i < buttons.length; i++){do something with buttons[i]}