从按钮数组修改按钮
Modify buttons from an array of buttons
我正在尝试编写一个程序,以便每当按下名为 '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.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)
代码:
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;
}
});
}
}
您不能像这样将引用存储在初始化程序数组中
Button[] buttons = {front,a,b1,b2,b3,b4};
但是为什么呢?放手去Array Initializers
The length of the array to be constructed is equal to the number of
variable initializers immediately enclosed by the braces of the array
initializer. Space is allocated for a new array of that length. If
there is insufficient space to allocate the array, evaluation of the
array initializer completes abruptly by throwing an OutOfMemoryError.
Otherwise, 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;
}
});
您可以尝试使用新的 Button[size],如下所示:
// 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};
然后当您将 Button 分配给数组成员之一时:
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);
}
}
for(int i = 0; i <= buttons.length; i++){do something with buttons[i]}
永远不是有效的 "for" 循环,原因很简单。它总是会给你 NullPointerException 因为在循环的最后一个循环中当 i == buttons.length();您正在尝试对按钮 [buttons.length()] 执行根本不存在的操作。
尝试for(int i = 0; i < buttons.length; i++){do something with buttons[i]}
我正在尝试编写一个程序,以便每当按下名为 '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.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)
代码:
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;
}
});
}
}
您不能像这样将引用存储在初始化程序数组中
Button[] buttons = {front,a,b1,b2,b3,b4};
但是为什么呢?放手去Array Initializers
The length of the array to be constructed is equal to the number of variable initializers immediately enclosed by the braces of the array initializer. Space is allocated for a new array of that length. If there is insufficient space to allocate the array, evaluation of the array initializer completes abruptly by throwing an OutOfMemoryError. Otherwise,
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;
}
});
您可以尝试使用新的 Button[size],如下所示:
// 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};
然后当您将 Button 分配给数组成员之一时:
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);
}
}
for(int i = 0; i <= buttons.length; i++){do something with buttons[i]}
永远不是有效的 "for" 循环,原因很简单。它总是会给你 NullPointerException 因为在循环的最后一个循环中当 i == buttons.length();您正在尝试对按钮 [buttons.length()] 执行根本不存在的操作。
尝试for(int i = 0; i < buttons.length; i++){do something with buttons[i]}