Repainting in while loop - java

I know that this question has been asked many times in a similar way on this platform. I've already spent a few hours trying the answers on my code (Threats and much more), but nothing has worked for me so far. So I'll ask the question here again specifically for my situation. I am currently programming a card game and would like to flip a coin before a card is played. I have already animated this as a gif and the coin toss logic works too. Now I want to get the animation into my program. For this I wrote a while loop which runs for 2 seconds. In this I would like to repaint, but the paint method (like many others had the problem before) is not called. This is my code in my public boolean cointoss() method for it:
cointossed = true;
long startTime = System.currentTimeMillis();
long elapsedTime = 0L;
while (elapsedTime < 2*1000) {
//Used this beacuse I thought my PC isnt fast enough
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
paintImmediately();
elapsedTime = (new Date()).getTime() - startTime;
}
cointossed = false;
In my paint() method there is the following Code, to draw the gif:
if(cointossed) {
g.drawImage(gif, 20, 20,100 , 100, null);
}
Somebody has an idea for my specific case?

Thx to MadProgrammer for helping me out with this.
I dont know if you mean it like that, but this worked for me:
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Timer abgeschlossen");
cointossed = false;
repainter.setRepeats(false);
}
};
ActionListener rep = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
repaint();
}
};
Timer timer = new Timer(2000 ,taskPerformer);
Timer repainter = new Timer(20 ,rep);
With this I created my own while loop where I can call repaint();
Just started both timers and my gif plays :D

Related

Changing the delay of the timer without creating a new one every time the method runs

So basically I have a timer method in my program which uses the integer z as it's parameter as well as the delay for the timer itself. But every time I run this method, it creates a new timer not deleting the old one. So I decided to add an if else block that made it so that it only created a timer on the first time but now it's saying that it might not have been initialized because it was initialized in the if else block. Can someone help me?
public void timer(int z) {
int count = 0;
Timer tester;
z = (60000 / z);
decide = true;
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {noteDecider();}
};
if(count == 0) {
tester = new Timer(z, taskPerformer);
tester.start();
}
else {
tester.setDelay(z);
tester.start();
}
count++;
}
I would say that if you are concern about optimizing your code you should look into optimizing your Timer class. Like moving the ActionListener object inside Timer itself and more. All your timer(int z) method is doing is trying to use an object to keep track time not managing the lifecycle of Timer objects.

How to create a countdown timer in a Java Applet?

I'm working on a final project for school with a Java applet that counts down from a given interval to zero. When a Rectangle on screen experiences a mouse down event, it is supposed to execute the timer; however this does not occur; the program ends up crashing. I've seen a lot of examples of timers online, but many are using Java's built in timer class, which I am not using. I figured there must be a more basic way to do a simple timer. All variables have been declared at the top of the class.
public boolean mouseDown(Event e, int x, int y)
{
if(start.inside(x,y))
{
timerAct = true;
startTime = System.currentTimeMillis() / 1000;
endTime = startTime + interval;
while (System.currentTimeMillis() / 1000 < endTime) {
while (startTime != System.currentTimeMillis() / 1000) {
startTime += 1;
timeLeft = (endTime - startTime);
}
}
timerAct = false;
}
repaint();
return true;
}
The logic seems to workout okay because this began as System.out.println(), and it worked just fine. Then, it was converted to store the variable timeLeft. In the paint method, I have
g.drawString("Time: " + timeLeft, 420, 180);
to print the the time remaining. I also have the update method; but it doesn't seem to make a difference. And I know the issue isn't because I'm changing a variable. My mouse down method has an if statement with a different rectangle that tracks clicks (not shown), and it updates a counter of clicks on screen in the applet window without any issue. Any help is greatly appreciated.
Check this. It's pretty self explanatory.
Here's how you would code a simple countdown timer. This code needs to be run in a separate thread and not the Event Dispatch thread.
private void countdownTimer(int intervalSecs) {
long endTime = System.currentTimeMillis() + (intervalSecs * 1000L);
while (System.currentTimeMillis() < endTime) {
sleep();
repaint();
}
}
private void sleep() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void repaint() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
panel.repaint();
}
});
}

Displaying JLabel movement

I am attempting to create a simple animation in which a series of bubble rotate around a centre point. I have one version of animation where the bubbles spread from the centrepoint before they begin to rotate, which works fine, but as soon as I click one of the images (which sparks the animation) the screen freezes for a moment and then the bubbles appear in their end position, rather than showing each step they made.
What I have so far is:
while(bubble[1].getDegree() != 270)
{
long time = System.currentTimeMillis();
//the below if statement contains the function calls for
//the rotating bubble animations.
next();
draw();
// delay for each frame - time it took for one frame
time = (1000 / fps) - (System.currentTimeMillis() - time);
if (time > 0)
{
try
{
Thread.sleep(time);
}
catch(Exception e){}
}
}
public void draw()
{
for(int i = 1; i < bubble.length; i++)
{
iconLabel[i].setLocation(bubble[i].getX(), bubble[i].getY());
textLabel[i].setLocation((bubble[i].getX()+10),(bubble[i].getY()+10));
}
}
For clarity, the method "next()" merely changes the position of the bubble to the appropriate place, I know this to be functioning as I have had the animation work before but once I implemented the animation to JLabels it stopped working.
Any help would be appreciated.
The drawing is frozen because you block the event dispatch thread. Drawing is done in the same thread as the while loop, and since the loop prevents anything else happening while it's running, swing can get to drawing only after the loop is finished, so only the last position is drawn.
Use a swing Timer instead:
timer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// whatever you need for the animation
updatePositions();
repaint();
}
});
timer.start();
And then call timer.stop() when all the frames you need have been processed.

Chess stopwatch working irregularly

I have a problem with a Timer in a chess i'm doing. It's working "fine", except it counts seconds two on two (2:00 > 1:58 > 1:56, etc.. but that's with a 1-second interval, not 2-second interval)
here' the code where i define, start, and end the timer:
private void setTime(){
totalTime=20;
whiteSec=0;
whiteMin=totalTime;
blackSec=0;
blackMin=totalTime;
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(whiteActive){
if(whiteSec>0) whiteSec-=1;
else{
whiteMin-=1;
whiteSec=60;
}
if(whiteMin==0 && whiteSec==0) endGame();
else GUI.setPlayerTime(whiteMin, whiteSec);
}else{
if(blackSec>0) blackSec-=1;
else{
blackMin-=1;
blackSec=60;
}
if(blackMin==0 && blackSec==0) endGame();
else GUI.setPlayerTime(blackMin, blackSec);
}
}
};
chessTimer = new Timer(1000, taskPerformer);
}
//start
whiteActive = true;
setTime();
wCastling = true;
bCastling = true;
canEnPassant = false;
GUI.setPlayerTime(whiteMin, whiteSec); //this writes the time in some JLabels.
guiRefresh();
activePiece = null;
chessTimer.start();
//end
private void endGame(){
GUI.endGame(checkMate); //shows an endgame JOptionPane
chessTimer.stop();
}
I'd appreciate any help!
While I do not believe a Timer can be started twice, multiple calls to setTime() would create multiple timers, each of which would independently decrement the fields (until the first is garbage collected, which may or may not happen). If you call the method twice in a row, the two Timer objects would coexist for a while, and it would probably decrement twice per second; calling stop() would stop one of the timers and keep the other around.
As a debugging step (and a good practice overall), check that you don't already have a timer before you create a new one:
/* ... */
if (chessTimer != null) throw new IllegalStateException("setTime already called");
chessTimer = new Timer(1000, taskPerformer);
To fix it, track down the duplicate call, or band-aid over it by replacing the IllegalStateException with chessTimer.stop();.
from http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html: This class does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method.

jSlider code causes the application to hang

This jSlider code causes the application to hang.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
for(int i=0;i<100;i++)
{
jSlider1.setValue(i);
Thread.sleep(3000);
}
} catch (InterruptedException ex) {
Logger.getLogger(AsdView.class.getName()).log(Level.SEVERE, null, ex);
}
}
thank you guys i am updating the answer
Timer time = new Timer(100, new ActionListener() {
int percent = 0;
#Override
public void actionPerformed(ActionEvent e) {
percent++;
if (percent>100)
percent = 0;
jSlider1.setValue((int)(100*(percent/600.0)));
}
});
time.start();
I am guessing you are trying to do some kind of smooth scroll.
That code freezes because the event thread that handles the window painting, sizing, etc..., is being frozen by you executing Thread.sleep(3000), 100 times.
I would recommend that you use a Swing timer that changes the scroll bar little by little.
i don't know why you put the sleep for 3 secs and that too in for loop of 100
3*100 = 5 mins so it will hang upto 5 mins
remove Thread.sleep(3000);
it will work fine and won't hang
When you say your application 'hangs', that generally means that you have some sort of deadlock that prevents your threads from making progress. Is that what you're observing in your program? The way it's currently written, the current thread of execution will take at least 300 seconds to complete. Is this work being done on the main thread of execution? If so, you may want to consider creating a new Thread to do this work.

Categories

Resources