I am trying to create a simple wack-a-mole in android. I created an array of buttons. When users clicks "start" I want to start a thread for each button . This thread will toggle the button in on and off state. I coded the application in swing(java) it works well. I am trying the same in android but it is creating problems. Please suggest what is wrong. I am starting a thread for each button but the application terminates. If I just start only one thread for any particular button then it works fine.
EDIT: Even after hard coding the buttons thread it is crashing on the click. Nothing is displayed in the logcat.
Creating the buttons : all buttons are intialized I am able to click on them and their action perform is working. Code written in oncreate method.
int j=0;
for (int k = 0; k <ROWS; k++) {
TableRow row = new TableRow(this);
//inner loop:
for (int l = 0; l < COLS; l++) {
btn[j] = new Button(this);
TableRow.LayoutParams tr = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
layout.setWeightSum(12.0f);
tr.setMargins(left, top, right, bottom);
btn[j].setLayoutParams(tr);
row.addView(btn[j]);
j++;
}
EDIT: COde written on onclick() listener of start(some other button from above created buttons) button. If I start only one thread the application works, but crashes if I ret to create mutiple thread. Is it not the correct way of creating thread? I sont think ASYNCTASK is useful here but comments are welcome.
start.setOnClickListener(new Button.OnClickListener() {
EditText timer = (EditText) findViewById(R.id.time);
// Called when user clicks the start button
public void onClick(View v) {
Log.i("thread started for ", btn[0]+"");
ButtonsThread bt2 = new ButtonsThread(btn[0]);
bt2.start();
ButtonsThread bt3 = new ButtonsThread(btn[1]);
bt3.start();
ButtonsThread bt4 = new ButtonsThread(btn[2]);
bt4.start();
ButtonsThread bt5 = new ButtonsThread(btn[3]);
bt5.start();
ButtonsThread bt6 = new ButtonsThread(btn[4]);
bt6.start();
}});
Please suggest why this for loop is crashing the application.
Question 2: When I am creating the buttons in oncreate() method I want to attach a listener to them.
I created a class implementing onClickListener() and attached its object on all the buttons :
// this was the wrong code which I corrected now.
for (int k = 1; k < 10; k++) {
TableRow row = new TableRow(this);
//innerloop:
for (int l = 1,j=0; l < 4; j++,l++) {
btn[j] = new Button(this);
btn[j].setEnabled(true);
//listner class
Score scoreListener = new Score();
btn[j].setOnClickListener(scoreListener);
row.addView(btn[j]);
this is also causing the application to fail if I click any button.
This is the code of Thread class:
class ButtonsThread extends Thread {
Button moleButton;
ButtonsThread(Button b) {
this.moleButton = b;
Log.i(TAG,"buttone thread created"+b);
}
public void run() {
while (timerInLong > 0) {
Log.i("while","while loop ");
try {
MapLocation.this.runOnUiThread(new Runnable() {
#Override
public void run() {
moleButton.setEnabled(true);
moleButton.setText(":-)");
}
});
moleButton.runOnUiThread(new Runnable() {
#Override
public void run() {
moleButton.setEnabled(true);
moleButton.setText(":-)");
moleButton.setBackgroundColor(Color.BLUE);
}
});
Thread.sleep(1000);
moleButton.post(new Runnable() {
#Override
public void run() {
moleButton.setEnabled(false);
moleButton.setText(":-(");
moleButton.setBackgroundColor(Color.RED);
}
});
Thread.sleep(1000);
You're not consistent in your treatment of how many buttons are in your array:
In the "working" code you use btn[0].
In the "problem" loop you use btn[1], btn[2], btn[3], btn[4].
In the button creation loop you initialize btn[0], btn[1], btn[2] only, but you repeatedly reinitialize those elements with 9 different buttons each.
It's hard to make sense of this but it seems you're leaving btn[3] and btn[4] uninitialized, probably causing a NullPointerException when you start using them. (You've neglected to say what exception you're getting...)
Be careful with your loop conditions. Unless you want to treat specially the first element of an array you shouldn't write a loop of the form:
for (int k = 1; k < N; k++)
Much more often you'd want to start at 0:
for (int k = 0; k < N; k++)
or for some uses, start at 1 and use <= as the boundary condition:
for (int k = 1; k <= N; k++)
I can't answer your question 2 because you say you've post the score listener code and you haven't.
Related
Recently, I have been making a simple board game android app. This game takes place on 7x7 grid, and I have made buttons for all of the squares.
This is not my first time doing this, and not only making the layout but also writing onClick() for each of those buttons were hard work. Thanks to the matrix array(int state[7][7] and Button board[][]=new Button[7][7]), I can shove all 49 codes into one function, but writing like
board[0][0]=(Button)findViewById(R.id.board00);
board[0][1]=(Button)findViewById(R.id.board01);
int i;
for(i=0;i<2;i++){
board[0][i].setOnClickListener(new OnClickListener() {
public void onClick(View v){
my_function(0,i);
}
}
(I had to write somewhat full code because the last time I omitted a part of the code, everyone was talking that I missed that part.)
will make all the buttons focus on the resulting i rather than the number it is originally meant for. (I know that part, don't just end up telling me "That won't work because~".)
So, my question is this: is there any way to make the [i][j] button to call my_function(i,j) for each of the i and j, rather than typing one by one or generating the code?
P.S. I didn't do much activities here, and I don't know how to look for my type of questions effectively, or verify if any question actually has my answer. If you find any question with the same answer, please tell me. I did search for this though.
If you want to keep the anonymous class then this should work
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++){
final int ii = i;
final int jj = j;
board[j][i].setOnClickListener(new OnClickListener() {
public void onClick(View v){
my_function(ii, jj);
}
}
Don't use an anonymous class. Make a full class. Then it can have a constructor you can call and pass in parameters. For example
private static class MyButtonListener implements OnClickListener {
int i;
int j;
public MyButtonListener(int i, int j) {
this.i = i;
this.j = j;
}
public void onClick(View v){
my_function(i, j);
}
}
Then in your loops, create a new MyButtonListener(i,j) instead of an anonymous class.
I was looking through some topics but couldn't find exact answer or at least couldn't get it right. What happens in the code is that i create one button for each row in my database and each button is supposed to have an OnClick that sends us to another activity along with some values(each button is supposed to have different value) but in the end it seems like i get the same value for all of my buttons which makes me think that it only creates 1 view for all of the buttons.
Cursor przepis = bazaUzytkownikow.rawQuery("SELECT * FROM przepisy", null);
int liczba_wierszy = przepis.getCount();
przepis.moveToPosition(0);
for (int i = 0; i < (liczba_wierszy/4)+1; i++) {
LinearLayout row = new LinearLayout(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
for (int j = 0; j < 4; j++) {
if((przepis.moveToPosition((i*4)+j)!=false))
{
nrPrzepisu=(i*4)+j;
Button btnTag = new Button(this);
btnTag.setLayoutParams(new LayoutParams(115, 60));
btnTag.setText(przepis.getString(przepis.getColumnIndex("nazwa")));
btnTag.setTextSize(10);
btnTag.setId(j + 1 + (i * 4));
btnTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View t) {
// TODO Auto-generated method stub
Intent IdzPrzepis = new Intent(getApplicationContext(), DodajPrzepis.class);
IdzPrzepis.putExtra("ID_uzytkownika", ID_uzytkownika);
IdzPrzepis.putExtra("nr_Przepisu", nrPrzepisu);
startActivity(IdzPrzepis);
}
});
row.addView(btnTag);
}
}
layout.addView(row);
}
To make the code more clear for you - bazaUzytkownikow is my database, liczba_wierszy is the number of the rows that i got. I move the cursor to the beginning since it's where i want to start and i proceed to "cut" my data using 2 loops. I am aiming for 4 buttons in 1 row.
The part that i think doesn't work is the OnClick method where i want my button to switch activity and send nrPrzepisu which is basically adding a connection between my button and proper row in the database (In the other activity i want to set text, reading rows from database depends on which button you click).
I checked the other activity and it seems to be reading same nrPrzepisu everytime which usually equals the last value of nrPrzepisu=(i*4)+j when loops finish and it made me think that i somehow need to make different views for each button.
you are passing the same object to each onClick then changing that object with the next iteration. In the end all the onClicks have the same nrPzepisu object and it is returning the value which is whatever is last in this example.
int nrPrzepisu = (i*4) + j;
This way you aren't passing the same object into all the onClicks.
So I am creating Dynamically Allocated Buttons. I want to query my database and based on the table the user selects (which are the dynamic buttons) a new activity will open that the user can work with the specified table.
protected void createButtons(){
// dynamically created buttons work just need to
LinearLayout scrViewButLay = (LinearLayout) findViewById(R.id.scrollViewLinLay);
scrViewButLay.removeAllViews();
ArrayList<String> tanks = new ArrayList<String>();
tanks = dbHand.getTableList();
Button[] tankButtons = new Button[tanks.size()];
Log.i("DB_Tag", "DB Size = " + tanks.size());
for(int i = 0; i < tanks.size(); i++){
Log.i("DB_NAME_TAG", tanks.get(i));
}
for (int index = 0; index < tanks.size(); index++) {
tankButtons[index] = new Button(this);
tankButtons[index].setText(tanks.get(index));
scrViewButLay.addView(tankButtons[index]);
tankButtons[index].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Each buttons specific event
/*
* Left off here
*/
Intent intent = new Intent(MainAquariumActivity.this, ProfilesOptionsScreen.class);
startActivity(intent);
//How would I send tanks.get(index) to the new ProfilesOptionsScreen
}
});
}
// end of dynamically allocated buttons
}
I am assuming that you have to dynamically create the onClickListeners along with creating the buttons. Is there a simpler solution to this?
Android - get resources from XML
Hi,
I am developing an android app for a quiz game, the game has 24 questions, and each question has a String(question) and four ImageButton(answer), when user select the correctImageButton`, then they go to next question.
But the problem is, after selecting the first correct answer, the screen refreshes with a new question and a new set of images, but it freezes there, and no matter what I click, it will not go to next question. I have attached my code and any help appreciated!!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_game);
// set variables
int fourImageId[] = { R.id.1_4a, R.id.1_4b,R.id.1_4c, R.id.1_4d };
questionText = (TextView) findViewById(R.id.question1);
questionList = getResources().getStringArray(R.array.question);
correctAnswerIdList = ListOfImages.getListOfCorrectImages();
imageIdList = ListOfImages.getListOfImages(); //two dimension array
// give values to four image buttons
for (int i = 0; i < 4; i++) {
fourImages[i] = (ImageButton) findViewById(fourImageId[i]);
final int temp = fourImageId[i];
fourImages[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (temp==correctAnswerIdList[index]){
questionText.setText(questionList[index]);
for (int i = 0; i < imageIdList[index].length; i++) {
fourImages[i].setImageResource(imageIdList[index][i]);}
index++;
}
}
});}
Your temp variable never changes after all the button click listeners are set. Because of this, the if (temp==correctAnswerIdList[index]) statement will only successfully execute once.
Your for (int i = 0; i < 4; i++) statement needs to execute once for each new question. Right now it only executes once, sets up the new question and image buttons, but your app doesn't know where to go from there.
I have a sequence of buttons in android and I need to change the text of those buttons sequentially (slowly one by one) How can I achieve this? I cant apply any animation here?
Its really hard to tell exactly
what you want to do here but one option could be to use a TimerTask You could repeat changing the text of the buttons at whatever intervals you want. You could use a for loop to iterate over the buttons
Handler myHandler = new Handler();
// your buttons something like this
int[] ButtonArray = {R.id.button1,R.id.button2.....};
String[] stringArray = {"Hi","Hello","oi"....};
// get all the button
private Button[] myButtons=new Button[buttonArray.length];
for(int i = 0; i < buttonArray.length ; i++){
myButtons[i] = (Button) findViewById(mAlphabetsId[i]);
}
//Handler to do repetitive task
.................
Start The repetitive task
counterValue = 0;
Size =buttonArray.length; //Number of buttons
myHandler.postDelayed(mMyRunnable, speed);
.............................
private Runnable mMyRunnable = new Runnable()
{
public void run()
{
if(counterValue<Size){
myButtons[counterValue].setText(stringArray[CounterValue]);
myHandler.postDelayed(mMyRunnable, 1000); //Call again with 1 sec delay
counterValue++;
}else{
myHandler.removeCallbacks(mMyRunnable);
counterValue=0;
}
}
};
This code may contain errors since I did it in a hurry. Try it first.
Let me know if you get stuck.