从按钮阵列修改按钮
我正在尝试编写一个程序,以便每当按下名为'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;
}
});
}
}
您可以尝试使用新的按钮【尺寸】,像这样:
// 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);
你分配一个对象front
不buttons[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 length
,and each component of the array is initialized to its default value
所以这里的引用将只由值替换意味着null
因此他们不能再保持变化的轨迹在实际的参考值
所以解决的办法是根据要求的长度声明array
或ArrayList
并添加对它的引用。
// {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]}
发布错误的完整logcat。不要修改或修剪 –
使用'for(int i = 0; i
@Pavneet_Singh仍然导致上述错误中显示的空指针异常 –