Blink circle with thread and handler but impossible to stop it - java

I develop an application and I want to make a circle blink when you click on a button. I have 8 circle on my view and I want them blinking separatly. I use this code :
public void blink(final View id, final int position, final boolean bool) {
final Handler handler = new Handler();
Thread th = new Thread(new Runnable()
{
#Override
public void run() {
final int timeToBlink = 250;
try {
Thread.sleep(timeToBlink);
} catch (Exception e) {
e.printStackTrace();
}
handler.post(new Runnable()
{
#Override
public void run()
{
if (id.getVisibility() == View.VISIBLE) {
id.setVisibility(View.INVISIBLE);
} else {
id.setVisibility(View.VISIBLE);
}
blink(id,position,true);
}
});
}
});
th.setName(Integer.toString(position));
aThread.add(th);
th.start();
where id is the id of the circle
but I can't stop blink with th.interupt
anyone can help me please ?

Thank to #jibysthomas i fixe my problem i use this link and i made this :
final Animation animation = new AlphaAnimation(1, 0);
animation.setDuration(250); // duration - half a second
animation.setInterpolator(new LinearInterpolator());
animation.setRepeatCount(Animation.INFINITE);
animation.setRepeatMode(Animation.REVERSE);
and i call this annimation on my circle.
Thanks a lot to jibysthomas

Related

Drawing animation in a Nattable OverlayPainter

I am trying to render a loading animation on top of a nattable. I use the OverLayPainter mechanism to draw a "glasspane" and some text on top of the table, and this works perfect:
public class MessageOverlay
implements IOverlayPainter {
....
#Override
public void paintOverlay(final GC gc, final ILayer layer) {
this.currentGC = gc;
this.currentLayer = layer;
if (visible) {
currentGC.setAlpha(200);
currentGC.fillRectangle(0, 0, currentLayer.getWidth(), currentLayer
.getHeight());
drawMessage();
if (withLoadingAnimation) {
showAnimation = true;
}
} else {
showAnimation = false;
}
}
}
However, the paintOverlay method is not called regularely but rather everytime the table changes.
To be able to display a smoothe animation, I added a new thread
final Thread animatorThread = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Thread.sleep(1000 / fps);
} catch (final InterruptedException e) {
break;
}
display.asyncExec(new Runnable() {
#Override
public void run() {
if (showAnimation && !currentGC.isDisposed()) {
final Image currentImage = getNextImage();
final int posX = currentGC.getClipping().width / 2
- currentImage.getBounds().width;
final int posY = currentGC.getClipping().height / 2
- currentImage.getBounds().height;
currentGC.drawImage(currentImage, posX, posY);
}
}
});
}
}
});
animatorThread.start();
As you can see it tries to access the graphics context this.currentGC set in the paintOverlay method. My problem is, that currentGC within the animatorThread is always disposed.
How can I a.) ensure that the context is not disposed in the thread or b.) solve this in an alternative way?
Thanks for the help.
You could try to create a new GC with the current NatTable instance and if needed pass the config from the passed in GC instance. Then you are in charge of disposing the GC instance and should not have the risk of a disposed GC outside your thread.
A simple example could look like the following snippet that simply shows the pane for 1000ms and then removes it again. You need of course to change the logic to be more dynamic with regards to your loading operation then:
AtomicBoolean paneThreadStarted = new AtomicBoolean(false);
...
natTable.addOverlayPainter(new IOverlayPainter() {
#Override
public void paintOverlay(GC gc, ILayer layer) {
if (this.paneThreadStarted.compareAndSet(false, true)) {
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
GC currentGC = new GC(natTable);
currentGC.setForeground(GUIHelper.COLOR_WHITE);
currentGC.setBackground(GUIHelper.COLOR_BLACK);
currentGC.setAlpha(200);
currentGC.fillRectangle(0, 0, layer.getWidth(), layer.getHeight());
String load = "Loading data ...";
Point textExtent = currentGC.textExtent(load);
currentGC.drawText(load,
layer.getWidth() / 2 - textExtent.x / 2,
layer.getHeight() / 2 - textExtent.y / 2,
true);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentGC.dispose();
natTable.redraw();
}
});
}
}
});
This way you are able to show the pane again by changing the AtomicBoolean from the outside:
Button showPaneButton = new Button(buttonPanel, SWT.PUSH);
showPaneButton.setText("Show Pane");
showPaneButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
this.paneThreadStarted.set(false);
natTable.redraw();
}
});

Cannot call constraintLayout.remove() from another thread;

Lets say I have a ImageView that executes at a click of a Button:
final ImageView ball = new ImageView(v.getContext());
ball.setImageResource(R.drawable.ball_1);
gameConstraintLayout.addView(ball);
When I click that button, it first off makes the ball appears , creates and runs another thread that tell itself to sleep 1000 milliseconds sleep(long millis) then removes the ball by calling ConstrainLayout.removeView(view)
Here is the full minimal code:
final ImageView ball = new ImageView(v.getContext());
currentBullet.setImageResource(R.drawable.ball_1);
gameConstraintLayout.addView(ball);
ballAppears.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final ImageView ball = new ImageView(v.getContext());
currentBullet.setImageResource(R.drawable.ball_1);
gameConstraintLayout.addView(ball);
Thread thread = new Thread() {
#Override
public void run() {
try {
sleep(1000);
contraintLayout.removeView(ball)
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
});
Problem is;
The ball appears on screen, the other thread successfully sleeps for 1000 milliseconds, but, It crashes when It tries to remove the ball from the constraint layout in the other thread.
Logcat:
android.view.ViewRootImpl$CalledFromWrongThreadException: **Only the original thread that created a view hierarchy can touch its views**.
at android.support.constraint.ConstraintLayout.removeView(ConstraintLayout.java:645)
at com.mobilegames.***.******.GameActivity$1$1.run(GameActivity.java:51)
The code that causes the problem is:
gameConstraintLayout.removeView(ball_1);
AS it seems,I cant access the Constraint layout from the other thread but, I can still change the X and the Y of the ball.
I even tried running that piece of code in the UI theard runOnUIThread(...), but to no avail.
Here is the runONUIThread code:
shootTank.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final ImageView currentBullet = new ImageView(v.getContext());
currentBullet.setImageResource(R.drawable.bullet_model1);
gameConstraintLayout.addView(currentBullet);
Thread thread = new Thread() {
#Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
gameConstraintLayout.removeView(currentBullet);
}
});
}
};
thread.start();
}
});
Any possible solutions? Keep in mind that I change the X and Y's of the ball after every second.
AND YES, I did check other Questions. The answer in those ones said to simply run it on the UI thread, but of course I already tried that. If i run the sleep(long millis) into the UI thread, obliviously, the whole app would be irresponsible.
(This is not the full app; it was broken down into a much more simpler and understandable Question. I end up changing the ball's X and Y in the separate thread, but that inst what is causing the problem. Please tell me in comments if editing is necessary)
Sorry for small grammar mistakes
Use handler to perform your actions with some delay. For example:
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
gameConstraintLayout.removeView(currentBullet);
}
}, 1000); // here 1000 is delay in milliseconds (1sec)

Thread not resuming in Java?

I am using a thread to draw images onto a JFrame.
I added a keyListener to listen for the key P, when it is pressed, the drawing of images stops and when I press P again, the drawing should resume.
I tried using wait/ notify along with synchronized block for implementing this.
However only Pausing works, the resume never works.
Strange...
public static void main(String[] args)
{
static JFrame window1 = new JFrame();
static boolean isPaused=false;
Runnable r = new Runnable()
{
public void run()
{
while(true)
{
window1.paintImage();//fn to redraw an image
}
}
};
final Thread t = new Thread(r);
window1.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_P)
{
if(isPaused==false)
{
synchronized(t)
{
try
{
t.wait();
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
isPaused=true;
} else
{
t.notifyAll();
isPaused=false;
}
}
}
public void keyReleased(KeyEvent arg0){}
public void keyTyped(KeyEvent arg0){}
});
t.start();
}
}
You should go through the Javadoc of Object.wait.
When t.wait() is executed, the current thread is "paused", not t.
More exactly, you are pausing the SWING Thread that is in charge of handling inputs, not the Thread t that you created to redraw the image.
t.wait() makes the SWING Thread to wait until it receive a notify() which will never come because the t.notifyAll() can only be reached by this same SWING Thread (so it is like you are going to sleep and you are waiting for yourself to wake you up... good luck with that).
Here is one solution to fix it (not the best though, since it does not care about synchronization):
final boolean [] pause = new boolean []{false};
Runnable r = new Runnable()
{
public void run()
{
while(true)
{
if(!pause[0])
window1.paintImage();//fn to redraw an image
}
}
};
...
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_P)
{
if(!pause[0])
{
pause[0] = true;
} else
{
pause[0] = false;
}
}
}

How to execute function ONLY after all actions are finished in Cocos2d

Can you guys tell me how can I execute function updateTiles() ONLY after all nodes' actions in function slideTiles(String s) are finished? I tried adding some while loop but it freezes whole program. After running functions one after another the animations just don't show up.
public boolean ccTouchesEnded(MotionEvent event)
{
CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));
x2=location.x; y2=location.y;
float diffY = y1-y2;
float diffX = x1-x2;
if (Math.abs(diffX)>Math.abs(diffY)&&diffX<0)
move="right";
else if (Math.abs(diffX)>Math.abs(diffY)&&diffX>=0)
move="left";
else if (Math.abs(diffX)<=Math.abs(diffY)&&diffY<0)
move="up";
else if (Math.abs(diffX)<=Math.abs(diffY)&&diffY>=0)
move="down";
int row=(int)(y1/TILE_SQUARE_SIZE);
int column=(int)(x1/TILE_SQUARE_SIZE);
slideTiles(move);
//wait for animations to finish
int sum=0;
boolean actionDone=false;
while (!actionDone)
{
for (CCNode c : tilesNode.getChildren())
{
sum+=c.numberOfRunningActions();
}
//String s=sum+"";
//statusLabel.setString(s);
if (sum==0){
actionDone=true;
break;
}
sum=0;
}
updateTiles();
return true;
}
//////
public void slideTiles(String move)
{
// Increment the moves label and animate the tile
CCBitmapFontAtlas moveslabel = (CCBitmapFontAtlas) getChildByTag(MOVES_LABEL_TAG);
moves++;
moveslabel.runAction(CCSequence.actions(
//CCDelayTime.action(0.25f),
CCScaleTo.action(0.2f, 6/5f),
//CCDelayTime.action(0.25f),
CCScaleTo.action(0.2f, 5/6f)
));
moveslabel.setString("Moves:\n " + CCFormatter.format("%03d", moves ));
if (move.equals("up"))
{
for (int start=NUM_COLUMNS; start<2*NUM_COLUMNS; start++)
for (int y=start; y<NUM_COLUMNS*NUM_ROWS; y+=NUM_COLUMNS)
{
if (tileNumbers[y]!=EMPTY)
{
for (int f=start-NUM_COLUMNS; f<y; f+=NUM_COLUMNS)
{
if (tileNumbers[f]==EMPTY)
{
//y->f
CGPoint moveTo = tilesNode.getChildByTag(f).getPosition();
CCMoveTo movetile = CCMoveTo.action(0.25f, moveTo);
CCSequence movetileSeq = CCSequence.actions(movetile);//CCCallFunc.action(this,"stopAction"));
tilesNode.getChildByTag(y).runAction(movetileSeq);
tileNumbers[f]=tileNumbers[y];
tileNumbers[y]=EMPTY;
break;
}
}
}
}
}
Edit: Is this kind of solution correct? It works surprisingly well.
public boolean ccTouchesEnded(MotionEvent event)
{
...
...
slideTiles(move);
float time = 0.25f+0.05f; //0.25f is time of moveTo action for each tile
CCDelayTime delay = CCDelayTime.action(time);
CCCallFunc cA = CCCallFunc.action(this, "updateTiles");
CCSequence se = CCSequence.actions(delay, cA);
runAction(se);
return true;
}
Generally, you shouldn't use while loop to wait in UI thread , it will cause big problem you have saw it.
You should use Thread to do this waiting job.
new Thread(new Runnable() {
#Override
public void run() {
while(true){
//here you wait forever doesn't matter the UI thread.
if(everythingDone) {//here to add your condition
new Handler().post(new Runable() {
#Override
public void run() {
//Here you can do what you want and will be done in UI Thread
}
});
}
}
}
}).start();

How stop object in TimerTask?

I have 6 objects in the class GUI which are moving through the code:
Anim anim = new Anim();
Timer timer = new Timer();
timer.scheduleAtFixedRate(anim, 30, 30);
When an object comes to a point I want to stop it. In class Anim I'm doing:
public class Anim extends TimerTask {
#Override
public void run() {
if (t1.x == 300 && t1.y == 300) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
It stops application, and I want have stayed at a concrete object. How to do it?
EDIT:
Ok, now it works well, does not interfere with other objects. But the object is moving on and after 1 second back to the starting position. I wish the whole time he was in the same position when a sleep.
if (Main.auto1.x == 700 && Main.auto1.y == 350) {
timer = new javax.swing.Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Main.auto1.x = 700;
Main.auto1.y = 350;
}
});
timer.setRepeats(false);
timer.start();
Use Swing Timer instead of Thread.sleep() and Java Timer in a Swing application that sometime hangs the Swing applicaion.
Read more How to Use Swing Timers
Sample code:
private Timer timer;
...
timer = new javax.swing.Timer(3000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//do what ever you want to do
// call timer.stop() when the condition is matched
}
});
timer.setRepeats(true);
timer.start();
EDIT
Please have a look at my another post How to fix animation lags in Java?

Categories

Resources