A very strange for loop bug in Java for Android? - java

I'm trying to alter the attributes of an array of Buttons, however I am getting some very strange errors. I am trying to loop through the buttons to edit the height attribute of each one, however when I set up a for loop (i=0; i<3; i++), buttonSkater[i].setHeight(buttonHeight); the result seems to be that 9 buttons are being altered! And when I set i<14 (there are 14 buttons), then the application crashes with a NullPointerException.
package com.rollerderby.lineuptracker;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
public class Setup extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.setup);
Button[] buttonSkater = new Button[14];
buttonSkater[0] = (Button) findViewById(R.id.buttonSkater1);
buttonSkater[1] = (Button) findViewById(R.id.buttonSkater2);
buttonSkater[2] = (Button) findViewById(R.id.buttonSkater3);
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
int buttonHeight = (screenHeight-60)/14;
for(int i=0; i<14; i++)
{
buttonSkater[i].setHeight(buttonHeight);
}
}
}
It seems a very strange error... Am I missing something obvious?
(Sizing the array wrong by creating it with space for new Buttons?)

Based purely on your code example, you're trying to access the 3rd to 14th element in an array that has only 3 indexes set (0 to 2), the other ones are (by default) initialized to null. As for the 14 buttons, are they 14 instances of just 3 buttons perhaps?

#fwielstra's answer is the right one, but for posterity, I thought I'd add some improvements to your code to help with resolving the problem in the future. Instead of doing this sort of code which is prone to the sort of error you had:
Button[] buttonSkater = new Button[14];
buttonSkater[0] = (Button) findViewById(R.id.buttonSkater1);
buttonSkater[1] = (Button) findViewById(R.id.buttonSkater2);
buttonSkater[2] = (Button) findViewById(R.id.buttonSkater3);
Instead you can initialize the size of the array like:
Button[] buttonSkater = new Button[] {
(Button) findViewById(R.id.buttonSkater1),
(Button) findViewById(R.id.buttonSkater2),
(Button) findViewById(R.id.buttonSkater3),
};
And when you are processing the array, instead of doing the following which means that if you change the size of the array, you need to do it in multiple places:
for (int i = 0; i < 14; i++)
...
I would use:
for (int i = 0; i < buttonSkater.length; i++)
...
Best of luck.

Without access to your XML, my guess is, if with a loop until 3 you're changing other 9 buttons it's because their id might be the same (i.e., copy/paste mistakes).
Also, from your code, it seems normal your application would crash with your loop until 14; after all, only the first 3 elements were instantiated. Once it gets to the 4th, it should access a null value, thus causing an error.

Well, for starters, your "14" loop is failing because only positions 0-2 have been assigned to anything. In Java, when you do
String[] strings = new String[5];
Nothing but the array has actually been initialized so
strings[0] == null;
and so on until you've actually initialized those values.
You need to manually initialize each value with
strings[0] = new String();
strings[1] = new String();
...
We'll need to see the other code to answer your question about modifying nine buttons.

Related

Final variable being changed without any = statements

I'm making an autoclicking project in java for personal use, and using the following method to get coordinates of a click from a class that extends MouseAdapter. The click is being done on a JFrame.
int[] mouseCoordinates = new int[2]; //The coordinates of the click
mouseCoordinates = mouseListenerExample.getCoordinates();
final int[] baseCoordinates = mouseCoordinates; //The base coordinates (no click) which is this problem//
int[][] totalCoordinates = new int[4][2]; //An array that collects all coordinates of 4 mouse clicks
for (int i = 0; i < 4; i++){ //the goal is to get the coordinates of 4 clicks
while (mouseCoordinates[0] == baseCoordinates[0]){
mouseCoordinates = mouseListenerExample.getCoordinates(); //The problem occurs here: when mouseListenerExample.getCoordinates() changes, mouseCoordinates is changed, baseCoordinates is also changing, which it shouldnt, since there are no statements that say so.
if (mouseCoordinates[0] != baseCoordinates[0]) {
break;
}
}
totalCoordinates[i] = mouseListenerExample.getCoordinates();
mouseListenerExample.setCoordinates(baseCoordinates);
mouseCoordinates = baseCoordinates;
}
Is there some statement that is changing baseCoordinates that I am missing?
Your baseCoordinates variable has been declared final, and so it cannot change, but since it is an int[] or int-array, it is a reference variable, and so what cannot change is the reference itself, not the state of the reference, and so the ints held within the array can (and in your case -- do) change.
You're changing the values held by mouseCoordinates. Since the baseCoordinates refers to the exact same int[] object, then this will likewise change the values for baseCoordinates. Best to create a completely new int object for the final variable if you don't want it changed.
Do something like:
final int[] baseCoordinates = new int[mouseCoordinates.length];
System.arraycopy( mouseCoordinates, 0, baseCoordinates , 0, mouseCoordinates.length );
So after some looking around, i just replaced the arrays with individual ints, and added a print statement right before the break, and it made it work.

Is there a better/shorter syntax for this?

I want to make it shorter, making them all true in one line, I don't know if this is possible
bckBtn.setEnabled(true);
cBtn.setEnabled(true);
addBtn.setEnabled(true);
btn7.setEnabled(true);
someone gave me this line but I couldn't understand it
Streams.of(obj1, obj2).forEach(obj -> obj.setEnable(true));
sorry if the question was easy, I'm new to java.
thanks again.
Here’s the simplest, pre-java 8 and conceptually easiest, code I could come up with.
for (Button button : Arrays.asList(bckBtn, cBtn, addBtn, etc)) {
button.setEnabled(true);
}
Try this:
Button[] buttons = {bckBtn, cBtn, addBtn, ...};
for (int i = 0; i < buttons.length; i++)
{
Button temp = buttons[i]; // seconds reference to the buttons[i] object
temp.setEnabled(true);
}

Randomly place a text on some buttons

I am trying to move, say a text or number in setText(Integer.toString()) format randomly on 4 different buttons at each click. I am able to obtain the object form of it, but it is worthless since I can't get that information out of it.
This is my code:
public void clickButton(View view){
List mo = new ArrayList();
mo.add(Button);
mo.add(Button1);
mo.add(Button2);
mo.add(Button3); // these are defined in OnCreate method
Random rko = new Random();
int koo = rko.nextInt(mo.size());
Object a = mo.get(koo);
Log.i("here", String.valueOf(mo.get(koo)));
I get this output in the logs up on each click
android.support.v7.widget.AppCompatButton{71c6fe0 VFED..C.. ...PH... 697,708-928,933 #7f0c0052 app:id/Button2}
android.support.v7.widget.AppCompatButton{71c6fe0 VFED..C.. ...PH... 697,708-928,933 #7f0c0052 app:id/Button3}
android.support.v7.widget.AppCompatButton{71c6fe0 VFED..C.. ...PH... 697,708-928,933 #7f0c0052 app:id/Button}
I am new to this. Please help
Thanks.
hi i believe that u should use tags on your buttons p = new Random().nextInt(21);
button.setTag(Integer.toString(alpha));
//here alpha is the text that you wanted to put on the button,get the text from button by using appropriate code
cbutton.setTag(Integer.toString(" "));
You could try writing AppCompatButton instead of Object and then you should be able to get the text of a button with a.getText(); and change the text of a button with a.setText();.
#Rushikesh You did not restrict the random generated number within the range of 0-4.
The size of array list of button is 4 so the the index must be 0-4 to avoid the IndexOutOfBoundsException
List mo = new ArrayList();
mo.add(Button);
mo.add(Button1);
mo.add(Button2);
mo.add(Button3);
int koo = (int)(Math.random() * (10-(mo.size()+1))); // generated number range will be 0-4
Object a = mo.get(koo);

How to call a variable using another variable?

So I have 44 buttons in my program, and for one of my methods I want to re-enable all of them. the buttons are easily named btn1, btn2, btn3...btn44. Is there a way I can use a for loop to enable all of them?
I would love to do something like this but I cannot find the resources necessary.
for(int i == 0, i < 44, i++){
btn<i>.setEnabled(true);
}
Without that I would have to go through each button
btn1.setEnabled(true);
btn2.setEnabled(true);
...
btn44.setEnabled(true);
I know this alternate method isn't that bad but I have similar areas in my code where a technique like the one I am looking for would be very useful. Thank you!
You should make an array of buttons:
Button[] buttons = new Button[44];
for (int i = 0; i < 44; i++) {
// Do stuff with buttons[i]
}
You can't get the value of a variable using its string name representation because that would not compile very well; it is possible but not just using Java and it would require some weird roundabout way of doing it. Just use an array.
Create a list to store all the buttons and the iterate it.
...
List<Button> buttons = new ArrayList<>();
buttons.add(btn1);
buttons.add(btn2);
...
buttons.add(btn42);
And then use that list for mass actions:
void setStatus(boolean enabled) {
for (Button b : buttons ) {
b.setEnabled(enabled);
}
}
You could add you Buttons to a collection, like a List (if you have not done so already). Then it's easier to iterate over them.
// this list will grow automatically when you add new elements
List<Button> buttons = new ArrayList<>();
// when you create a button in your code, add them to your collection/list
buttons.add(new Button("1"));
buttons.add(new Button("2"));
buttons.add(new Button("3"));
buttons.add(new Button("4"));
buttons.add(new Button("5"));
// etc.
// in Java 8 you can use lambdas to update your buttons like this
buttons.forEach(button -> button.setEnabled(true));
Just make sure you are importing the correct version of List.
I.e make sure you use this list import java.util.List; and not the one in the windowing toolkit (i.e. not import java.awt.List;)

Android/Java "Convert" String to Button

I have this code:
Button button1 = (Button) findViewById(R.id.button1);
Button button2 = (Button) findViewById(R.id.button2);
String object = "button";
int num;
num = r.nextInt(3 - 1) + 1;
String total = object + num;
I want do set the text for one of the buttons chosen randomly. Something like this:
button<num>.setText(some_text);
^ here instead of <num> should be 1 or 2
and has to be chosen randomly
Like Ondkloss said, you can add your buttons to an array, then randomly select one from that array.
Button[] buttonArray = new Button[2];
buttonArray[0] = button1;
buttonArray[1] = button2;
Random r = new Random();
buttonArray[r.nextInt(2)].setText(someRandomText);
Keep in mind that if you change the number of buttons you will need to change the numbers that I have used (new Button[2] & r.nextInt(2)). My solution works specifically for an array of length 2 containing only 2 buttons. But other than changing the numbers in the array creation and the random number generation to match the number of buttons you have, this solution should work just fine.
No, i want change the text of the button.
Then just do something like this
button1.setText("Just some strings here");

Categories

Resources