I'm developing my first android game without xml files for layouts in eclipse. This is calling MyGameView.class(extends View) from MyGameActivity.class(extends View implements OnTouchListener)
MyGameView myView;
myView = new MyGameView(this);
myView.setOnTouchListener(this);
setContentView(myView);
Everytime, I touch (MotionEvent.ACTION_DOWN), I update the Canvas in MyGameView.class with the following code. This is the code I use to update MyGameView.class from MyGameActivity.class.
myView.invalidate();
Yes it works!But I got a serious problem now.I need to move Canvas in MyGameView.class by every 0.3 second.I use Thread to update but it forced stop!!!! I tried again and again and again! I failed!
public void runtime() {
i = 0;
Thread timer = new Thread(new Runnable() {
#Override
public void run() {
while (i<1500) {
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
if (right) {
i++;
//This is static int a from MyGameView.
MyGameView.a += 2;
myView.invalidate();
}
else {
i = 1500;
}
}
}
}
});
timer.start();
}
Updating Static int or boolean to MyGameView.class from MyGameActivity.class with myView.invaldate(); is working. But I can't control it with Thread! Is there something wrong with my Thread running code?
It's probably up to Thread because I can move +2 along X-axis to right everytime I press (MotionEvent.ACTION_DOWN).
//I can Move with this code but not with Thread!
case MotionEvent.ACTION_DOWN:
MyGameView.a += 2;
myView.invalidate();
break;
With Thread, it stops! Please give me a solution for this! In other words, I need to count with time without error and update canvas on every count!
Invalidate must be called from the UI thread. Try calling
postInvalidate()
instead.
See this for reference.
Related
atm i have a problem with my actual Android application.
For explanation:
At first i want to show a Text in a TextView Char by Char. This is my actual Code for this
tvIntro.setText("");
final Handler textHandler = new Handler();
for(int i=0; i<intro.length();i++){
final int finalCount = i;
textHandler.postDelayed(new Runnable() {
#Override
public void run() {
tvIntro.setText(tvIntro.getText() + (intro.charAt(finalCount)+""));
}
}, 150 * i);
}
After the whole text is displayed, i want to play a sound and continuously change the Color of the Screen for 5 Seconds. For this, my code is:
myBackground.setBackgroundColor(Color.RED);// set initial colour
final Thread blink = new Thread(new Runnable() {
public void run() {
while (getRunning()) {
try {
Thread.sleep(100);
if(start[0] !=1){
mp.start();
start[0] = 1;
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
updateColor(myBackground);
whichColor = !whichColor;
}
}
});
private void updateColor(final RelativeLayout myBackground) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (whichColor)
myBackground.setBackgroundColor(Color.RED);
else
myBackground.setBackgroundColor(Color.GREEN);
}
});
}
All the functions are working, but i want too finish the first handler, before the second handler is executed. Furthermore the Second handler should stop after x seconds.
I have some problems understanding how the handler and the Threads work.
Would be nice if someone of you have a solution for me.
To delay the performing of tasks until a specified thread (or threads) finishes, add this line immediately after the thread you wish to wait on:
myThread.join();
And then immediately follow it with the code you wish to run after it finishes.
For your second problem, you can set a variable to be the value (in milliseconds) for the amount of time you want to wait before ending the thread, and then decrease that value by 100 (or whatever amount you choose to tell it to sleep for) each time the code runs. Have a check for the value to be less than or equal to zero, and then if that condition returns true, end the thread with an interrupt. So basically:
long timeToRun = 5000, sleepTime = 100;
// Your code here...
Thread.sleep(sleepTime);
timeToRun -= sleepTime;
if(timeToRun <= 0) {
myThread.interrupt();
}
There are likely more graceful ways to accomplish this, but at the very least this should solve your problems.
I'm trying to build "Stick Hero" board game using javafx (JDK8). I use
scene.setOnKeyPressed(e -> {
Thread thread = new Thread() {
#Override
public void run() {
if (e.getCode().equals(KeyCode.ENTER)) {
// do some graphical changes
playGame();
}
}
};
thread.start();
});
to listen to keyboard and by pressing enter the vertical line turns into a horizontal bridge and the human pass the bridge and this will continue until the length of bridge doesn't match the distance. Now i want to update UI during playGame() method is running. When i tried to do scoreLabel.setText(String.valueOf(score)); and update the scoreLabel text i encountered Not on FX application thread error. playGame() is something like
for (int i = 0; i < cycle; i++) {
goOneCycle();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
fixPosition();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and in goOneCycle(); and fixPosition(); i do some graphical changes but it does not shown until the end of the loop.
Now i have two questions. First why i can do stuff like scoreLabel.setLayoutX(500); but i cannot do scoreLabel.setText(String.valueOf(score)); i mean in the first case i do not encounter Not on FX application thread. And how i can update scoreLabel text. Notice that i already tried to use Platform.runLater() but when i use this animations and graphical changes will not shown in playGame() method, and just the final frame is shown -all of the animations is done but it does not shown.
So I have a view that is made of a single TextView in the middle and I change the text in this TextView according to the user's action, but when I use the following code:
if(condition == 1){
mainText.setText("Correct");
try {
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Random r = new Random();
int idx = r.nextInt(names.length);
random = (names[idx]);
mainText.setText(random);
condition = 0;
}
The mainText doesn't change to Correct, but it does change to random.
Any idea on how to fix this, thanks
You can not use delays on a UI thread, it will fail 100% of the time.
Set your text, and then post a runnable to the UI thread that delays your desired time, and then changes the text.
view.setText("something");
view.postDelayed(new Runnable(){
public void run(){
view.setText("somethingelse.");
}
}, 200);
So I have this really weird problem that I simply cannot understand why it doesn't work. I am building a strobe light as part of my app and have created a separate Strobelight class. When I call the turnOn method or update method, the intervals never are changed. I guess it would make it easier to explain using some code:
public class Strobelight{
private int delayOn, delayOff;
public void turnStrobeOn(){...}
public void update(int a_delayOn, int a_delayOff){
delayOn = a_delayOn;
delayOff = a_delayOff;
}
public void turnOn(int a_delayOn, int a_delayOff){
delayOn = a_delayOn;
delayOff = a_delayOff;
this.turnStrobeOn();
}
Depending on whether the strobe light is already on or not, one of these methods are called to change turn on the strobe light with the specified intervals or simply to change the intervals.
Instead of changing the intervals to something custom, the application just uses the smallest possible intervals when calling Thread.sleep() for the flashlight being on or off
EDIT: this is the thread code, and code that turns the flashlight on
public void turnStrobeOn(){
for ( int i = 0; i < 3; i++){
isInCycle = true;
cam = Camera.open();
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview(); // the flashlight is now on
lightIsOn = true;
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(delayOn);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
cam.stopPreview();
cam.release();
lightIsOn = false;
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(delayOff);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
} //end of for loop
isInCycle = false;
} // end of turnStrobeOn
You might want to get someone else's advice on this buy my best guess is that you can't be so specific on sleep(). Also don't forget to use miliseconds for that. I'd suggest using the android handler and doing postDelayed for this instead of sleeping.
How to pause / sleep thread or process in Android?
I'm attempting to make a basic app and for part of that app I needed a delay after a button is pressed to allow for a text view to show a word for a second, and then change to another word and then have that display for a second and show another word. S0 3 words, 2 delays. i achieve the first delay using postDelayed() which works fine.
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch(view.getId())
{
case R.id.bStart:
display.setTextColor(Color.YELLOW);
display.setText("READY");
start.setText("Restart");
timer.postDelayed(makePattern, 1000);
break;
}
}
The app displays "READY" for one second then opens a new thread and then starts the makePattern runnable which is where the problem is.
makePattern = new Runnable()
{
#Override
public void run() {
display.setTextColor(Color.GREEN);
display.setText("GO!");
for(int x = 0; x < level; x++) {
pattern[x] = crazy.nextInt(4);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
display.setText("IT WORKED");
}
}
};
Here it should be displaying "GO!", pausing the thread for a second and then displaying "IT WORKED". However when I run it on both my phone and the emulator it displays "READY" for 2 seconds and then skips to "IT WORKED" either displaying "GO!" for such a short amount of time that it can't be seen of skipping over it all together. I have already tried moving the setText("GO!") inside of the catch and that didn't work either. Any Help would be much appreciated.
THANK YOU!
You could create a second Runnable and schedule that using postDelayed, like you're doing for the first. In the same place you schedule the first for 1 second later, you could schedule the second to occur 2 seconds later, which would be 1 second after the first. Or, you could schedule it from within the first runnable for 1-second later. See the "OPTION" comments in the code below.
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch(view.getId())
{
case R.id.bStart:
display.setTextColor(Color.YELLOW);
display.setText("READY");
start.setText("Restart");
timer.postDelayed(makePattern, 1000);
timer.postDelayed(showItWorked, 2000); // <-- OPTION 1
break;
}
}
makePattern = new Runnable()
{
#Override
public void run() {
display.setTextColor(Color.GREEN);
display.setText("GO!");
for(int x = 0; x < level; x++) {
pattern[x] = crazy.nextInt(4);
}
timer.postDelayed(showItWorked, 1000); // <-- OPTION 2
}
};
showItWorked = new Runnable()
{
#Override
public void run() {
display.setText("IT WORKED");
}
};
And just to clarify what's going wrong in your existing code...
As Mael mentioned in his comment, your use of Thread.sleep is blocking the UI thread. Just because the the code is within a Runnable does not necessarily mean that it's running on another thread. From the Android documentation for Handler.postDelayed (I'm assuming "timer" is a Handler): "Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached."