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.
Related
I have a problem with implementation of my Game of Life in Java.
In GUI I have buttons which decide of inicial state of the game (oscilator, glider etc), then using Action Listener I set the first board and show it.
Then I have a function that count neighbours of my cell and set colors of my cells.
But I have a problem when I want to repeat game n times, because I don't know how to set time interval.
At this moment I don't see every step of game, but just the last one.
Below is my ActionListener:
private ActionListener buttonsListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == button1)area = setButton1(getBoardWidth(), getBoardHeight());
if (source == glider) area = setGlider(getBoardWidth(), getBoardHeight());
if (source == oscilator) area = setOscilator(getBoardWidth(), getBoardHeight());
setBoard(area, board);
}
};
Function setBoard() takes array of ints with 0 and 1, and convert it to JButton[][] array with colors.
I tried to use Overrided method run() that include startTheGame() function, which checks neighbourhood and set array of ints. I need to do this multiple times but I can't set time intervals.
#Override
public void run() {
startTheGame(area);
setBoard(area, board);
}
You should use this timer schedule.
So you have to define a custom TimerTask like this:
import java.util.TimerTask;
public class UserTimerTask extends TimerTask{
#Override
public void run() {
startTheGame(area);
setBoard(area, board);
}
}
And then wrapping your code like this:
// daemon means, background. If every task is a demon task, the VM will exit
Bolean isDaemon = false;
Timer timer = new Timer("nameOfThread",isDaemon);
TimerTask task = new UserTimerTask();
// Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay
// both parameters are in milliseconds
timer.schedule(task,0,1000);
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.
So, basically, I've got a swing game that has a swing timer. This is to wait after the computer has calculated what it will do until it turns because human's can't look so fast. When that timer executes, the next turn begins and the computer AI takes its turn.
Thing is, when both players are computers, this will theoretically stack timers into each other ad infinitum because inside the timer, the same timer will (indirectly) be called again, and again, and again. Does this generate data leaks and if so, what else can I do to archieve the same "waiting" process?
So, in pseudocode, this is what is happening:
public void computerTurn() {
...
new Timer(1000, new ActionListener() {
....
if (foo)
computerTurn()
}
}
You can do this:
ActionListener listener = (e) -> {
if (!foo) { // if not foo, don't repeat anymore
((Timer)e.getSource()).stop();
}
}
Timer timer = new Timer(1000, listener);
timer.setRepeats(true);
timer.start();
For some reason even though I am using the exact code example from oracle's website for the Swing Timer it is not waiting for 1 second. It just skips to the JOptionPane that says "Your score was etc etc".
Here is my source code for a school project. Why is this not working and not waiting for 1 second before running the rest of the code?
//Check to see if user has enetered anything
if(!answered)
{
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
afk = true;
incorrect += 1;
answered = true; //This breakes it out of the loop
}
A timer is used to run a callback after a specific amount of time. If you simply want to delay, you can either move the code to be run after the delay into the taskPerformer action listener.
Thread.sleep(1000) is not ideal here, because it will cause the UI to completely freeze as you will make the UI thread sleep.
What can do to have a Swing Timer object fire every 2 seconds for ten times and do a different thing in each firing? Using:
// task one
int delay = 2000;
Timer swingTimer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// task two
}
});
swingTimer.start();
only enables me to do two things. But I want to use the timer to execute one chunk of code, wait 2 seconds, execute another chunk of code, wait another 2 seconds, do another thing and so on and so forth for like 10 consecutive tasks. Thanks.
Use some kind of counter in your actionPerformed method to determine which cycle your up to....
private int cycle = 0;
//...
Timer swingTimer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
switch (cycle) {
case 0:
// Task #1
break;
case 1:
// Task #2
break;
case 2:
// Task #3
break;
default:
// All done...
((Timer)e.getSource()).stop();
}
cycle++;
}
});
You could set up a new non-repeating Timer at the conclusion of each actionPerformed, seeding it with the next ActionListener/task to be executed, but this can get messy quickly...
This is basic concept of the idea. You could devise a common interface for each task, add them to a List of some kind and simply use list.remove(0) to pop the next one of the List and execute it. You would continue until the List was empty.
private int cycle;
Timer swingTimer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
controller.callMethod(cycle); // controller decides what to do
cycle++;
}
});
And don't forget to stop the timer after it completes a desired number of cycles.