I have a CountDownTimer class that when it finishes counting down it should dispatch an event to main java (or any class that uses it) letting it know it has finished.
Here is my class:
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Label;
public class CountTimer {
private Label targetText;
private String direction;
private int minutes;
private int seconds;
private int totalSeconds;
private int timeTotal;
private int timeLoaded;
private Boolean test;
Timer timer;
public CountTimer(int min,int sec,String dir,Label targetTextField)
{
minutes = min * 60;
seconds = sec;
timeTotal = minutes + seconds;
if (dir == "down") {
totalSeconds = minutes + seconds;
}
else {
totalSeconds = 0;
}
if (targetTextField != null) {
targetText = targetTextField;
}
direction = dir;
}
public void start()
{
timer = new Timer(){
public void run(){
timeLoaded += 1;
if (direction == "up") {
totalSeconds++;
}
else {
totalSeconds--;
}
seconds = totalSeconds % 60;
minutes = (int) Math.floor(totalSeconds / 60);
String minutesDisplay = (minutes < 10) ? "0" + Integer.toString(minutes) : Integer.toString(minutes);
String secondsDisplay= (seconds < 10) ? "0" + Integer.toString(seconds): Integer.toString(seconds);
if (targetText != null) {
targetText.setText( minutesDisplay + ":" + secondsDisplay);
}
if (test=true) {
consoleLog(minutesDisplay + ":" + secondsDisplay);
}
if(timeTotal == timeLoaded) {
//DISPATCH CUSTOM EVENT TO MAIN.JAVA HERE
Window.alert("OK");
timer.cancel();
}
}
};
timer.scheduleRepeating(1000);
}
public int getTimeTotal()
{
return timeTotal;
}
public int getTimeLoaded()
{
return timeLoaded;
}
public int getProg()
{
return (int) Math.floor(timeLoaded/timeTotal*100);
}
public native final void consoleLog(String msg)/*-{
console.log(msg);
}-*/;
}
Please help, how can i do this?
I believe you are looking to implement the Publish-Subscribe pattern.
http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
You can allow your object to have subscribers register with it. Once you have finished your operation it can then notify the subscribers that it has finished.
Example:
public interface Subscriber {
public void notify();
}
public class Publisher {
private ArrayList<Subscriber> subscribers = new ArrayList<>();
public void addSubscriber(Subscriber s) {
subscribers.add(s);
}
public void doWork() {
System.sleep(100);
notifyAll();
}
private void notifyAll() {
for(Subscriber s : subscribers) {
s.notify();
}
}
}
There are several options.
If you have this requirement frequently, or you need to notify multiple Activities/widgets, you may consider using an EventBus:
How to use the GWT EventBus
Alternatively, your CountTimer can simply call a public static method in your main class:
MyApp.doSomething();
Related
else if(left || right) {
if(currentAction != WALKING) {
currentAction = WALKING;
animation.setFrames(sprites.get(WALKING));
animation.setDelay(40);
width = 30;
Here is the code I am having issues with. namely the animation.setFrames and setDelay the setFrames uses a BufferedImage array and the setDelay is a long variable. The two errors that come up are
The method setFrames(BufferedImage[]) is undefined for the type Animation
and
The method setDelay(Duration) in the type Animation is not applicable for the arguments (int)
public void setFrames(BufferedImage[] frames) {
this.frames = frames;
currentFrame = 0;
startTime = System.nanoTime();
playedOnce = false;
this is the code for the setFrames and the code of delay's setter is just
public void setDelay(long d) {
delay = d;
}
Any assistance is welcome.
There were none of these errors in the tutorial
EDIT: I have created a new Animation class in the constructor but it did not solve it. Added Animation class
package Entity;
import java.awt.image.BufferedImage;
public class Animation {
private BufferedImage[] frames;
private int currentFrame;
private long startTime;
private long delay;
private boolean playedOnce; played; e.g. an attack so it does not
public void Animation() {
playedOnce = false;
}
public void setFrames(BufferedImage[] frames) {
this.frames = frames;
currentFrame = 0;
startTime = System.nanoTime();
playedOnce = false;
}
public void setDelay(long d) {
delay = d;
}
public void setFrame(int i) {
currentFrame = i;
}
public void update() {
if (delay == -1)
return;
long elapsed = (System.nanoTime() - startTime) / 1000000;
if (elapsed > delay) {
currentFrame++;
playedOnce = true;
}
}
public int getFrame() {
return currentFrame;
}
public BufferedImage getImage() {
return frames[currentFrame];
}
public boolean hasPlayedOnce() {
return playedOnce;
}
}
Thank you to Bandreid for the answer.
It need the object to be added and a new object created.
I am not sure how to get this working. I want one this tread to stop once (startNumber == 0 || !Player.cCounting). !Player.cCounting is a boolean that is accessed. If either condition is met I want the loop to stop.
public class Console {
static long lastTime;
static boolean cCounting = true;
static long seconds = 0;
static long delta = 0;
static int startNumber = (int) Level.cookieTime / 1000;
Thread countDown;
public Console() {
cookieCountDown();
lastTime = System.currentTimeMillis();
}
public void cookieCountDown() {
countDown = new Thread(new Runnable() {
#Override
public void run() {
startNumber = (int) Level.cookieTime / 1000;
while (startNumber != 0) {
cCounting = Game.enter;
//System.out.println(cCounting);
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (startNumber > 0 && cCounting) {
long now = System.currentTimeMillis();
delta = now - lastTime;
if (delta >= 1000) {
delta = 0;
lastTime = System.currentTimeMillis();
System.out.println("cookie " + startNumber);// print countdown;
startNumber--;
System.out.println(Player.cCounting);
if (Player.cCounting = false) {
end();
}
}
}
}
}
});
countDown.start();
}
public void end() {
System.out.println(startNumber);
System.out.println(cCounting);
if (startNumber == 0 || !Player.cCounting) {
System.out.println("stop");
//countDown.interrupt();
//countDown.stop();
}
}
}
You just need to exit your loop. Replace your end(); method call with return;. and make startNumber and Player.cCounting volatile e.g. volatile static int startNumber
I have a class countdown timer that I want to reset but when it resets it wont start again.
Basicaly when the counter gets to 0 (when the status is "done"), sets x = 1 and then in the activity checks if x = 1 , and then the counter resets. When the reset method from within the class is called it shows that it has reset but it wont start counting again
Timer class:
public class countdown_timer {
private long pls;
private long millisInFuture;
private long countDownInterval;
private boolean status;
int x = 0;
public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
this.millisInFuture = pMillisInFuture;
this.countDownInterval = pCountDownInterval;
this.pls = pMillisInFuture;
status = false;
Initialize();
}
public void Stop() {
status = false;
}
public int GetNumberX() {
return x;
}
public void Reset() {
millisInFuture = pls;
x=0;
}
public void Start() {
status = true;
}
public void Initialize() {
final Handler handler = new Handler();
Log.v("status", "starting");
final Runnable counter = new Runnable() {
public void run() {
long sec = millisInFuture / 1000;
if (status) {
if (millisInFuture <= 0) {
Log.v("status", "done");
x = 1;
} else {
Log.v("status", Long.toString(sec) + " seconds remain");
millisInFuture -= countDownInterval;
handler.postDelayed(this, countDownInterval);
}
} else {
Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
handler.postDelayed(this, countDownInterval);
}
}
};
handler.postDelayed(counter, countDownInterval);
}
Activity that uses the timer class:
mycounterup = new countdown_timer(startcard, 1000);
xup = mycounterup.GetNumberX();
if (xup == 1) {
mycounterup.Reset();
mycounterup.Start();
Thanks for any help.
try changing your start method as and one thing more i don't know if its a typo or what change mycounter.Start(); to mycounterup.Start();
public void Start() {
status = true;
Initialize();
}
save the counter state so that next time if you have to pause or resume the thing you are able to do it also
You should change your Reset method:
public void Reset() {
millisInFuture = pls;
x=0;
Initialize();
}
I wrote a timer class. And I want to override its toString method. But when I call the toString method, it still returns the super implementation. (fully qualified name of the class)
Here is my timer class:
import android.os.Handler;
import android.widget.TextView;
public class Timer implements Comparable<Timer> {
private Handler handler;
private boolean paused;
private TextView text;
private int minutes;
private int seconds;
private final Runnable timerTask = new Runnable () {
#Override
public void run() {
if (!paused) {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
}
text.setText (toString ()); //Here I call the toString
Timer.this.handler.postDelayed (this, 1000);
}
}
};
//Here is the toString method, anything wrong?
#Override
public String toString () {
if (Integer.toString (seconds).length () == 1) {
return minutes + ":0" + seconds;
} else {
return minutes + ":" + seconds;
}
}
public void startTimer () {
paused = false;
handler.postDelayed (timerTask, 1000);
}
public void stopTimer () {
paused = true;
}
public void resetTimer () {
stopTimer ();
minutes = 0;
seconds = 0;
text.setText (toString ()); //Here is another call
}
public Timer (TextView text) {
this.text = text;
handler = new Handler ();
}
#Override
public int compareTo(Timer another) {
int compareMinutes = ((Integer)minutes).compareTo (another.minutes);
if (compareMinutes != 0) {
return compareMinutes;
}
return ((Integer)seconds).compareTo (another.seconds);
}
}
I can see that the text view's text is the fully qualified name of the Timer class. I even tried this.toString but it doesn't work either.
You're calling toString() from your anonymous inner class - the new Runnable() { ... }. That means you're calling toString() on your anonymous class instance, not on the Timer instance. I suspect you're getting a $1 in the output, showing that it's an anonymous inner class.
Try:
text.setText(Timer.this.toString());
... so that you call it on the enclosing Timer instance instead.
Here's a short but complete console app to demonstrate the difference:
class Test
{
public Test() {
Runnable r = new Runnable() {
#Override public void run() {
System.out.println(toString()); // toString on anonymous class
System.out.println(Test.this.toString()); // toString on Test
}
};
r.run();
}
public static void main(String[] args) {
new Test();
}
#Override public String toString() {
return "Test.toString()";
}
}
Output:
Test$1#15db9742
Test.toString()
So I have an NPC and I want it to change its appearance over a period of 5 minutes, or 10 minutes if you are a special player. The NPC changes twice and then completely removes itself. Once a player dies this NPC is placed in their current position. The NPC then starts to degrade over the period of 5 minutes and then eventually removes itself. This NPC allows the player to grab their lost items before the timer runs out. While the NPC is there, other players have the option of making the timer reset so they have more time to get there. I was able to make it degrade and send them a message saying the time they had left to get their items back. The only problem occurred towards the end, before it destroys itself. It constantly sends the player a message saying the time they had left rather than just once, and it never gets removed. Here is the code I have for it:
package com.rs.game.npc.others;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import com.rs.game.item.Item;
import com.rs.game.npc.NPC;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.utils.Logger;
public class Gravestone extends NPC implements Serializable {
private static final long serialVersionUID = -3293609625562930841L;
private transient Player player;
private long BEGIN_TIME;
private int currentGrave;
private final CopyOnWriteArrayList<Item> container;
private int MAX_TIME = 6*60000;//60000ms = 1 min
private int INTERFACE = 272;
private long timeLeft = (long) (System.currentTimeMillis() - BEGIN_TIME);
private int minutes;
public Gravestone(Player player, CopyOnWriteArrayList<Item> containedItems) {
super(6601, player, -1, false, false);
this.player = player;
this.BEGIN_TIME = System.currentTimeMillis();
if (player.isDonator())
this.MAX_TIME *= player.getDonator();
this.currentGrave = 6601;
this.container = containedItems;
setName(player.getDisplayName()+ "'s Gravestone");
player.sm("A gravestone has been left in the place you died to receive your items click on it.");
}
public Gravestone(Player player, CopyOnWriteArrayList<Item> containedItems, long time, int npcId) {
super(npcId, player, -1, false);
this.player = player;
this.container = containedItems;
setName(player.getDisplayName()+ "'s Gravestone");
}
public String getName() {
return player.getDisplayName()+ "'s Gravestone";
}
public void processNPC() {
if (hasFinished())
return;
setName(getName());
long timeElapsed = System.currentTimeMillis( ) - BEGIN_TIME;
int minute = 60000;
int minutesElapsed = (int) (timeElapsed / minute);
int maxMinutes = MAX_TIME / minute;
minutes = maxMinutes - minutesElapsed;
boolean pause = false;
if (!pause && (minutes == 5 && getId() == 6601 //first - degrade at 5 minutes stop and wait til unpause
|| minutes == 3 && getId() == 6602 //second - degrade at 3 minutes
|| minutes <= 0 && getId() == 6603)){ //third - degrade at 1 minute
degradeGraveStone();
pause = true;
} else if (pause && (minutes == 4 && getId() == 6602 //second
|| minutes == 2 && getId() == 6603)) //third
pause = false;
Logger.log("GraveStone", "Player "+ player.getDisplayName() +" time elapsed "+ timeElapsed +" minutes left "+ minutes +" Pause? "+pause);
}
public void handleOptions(Player p, int id, int npcId) {
switch (id) {
case 1:
sendMemorial(p);
break;
case 2:
if (npcId == 6601)
demolishGraveStone(p);
else
repairGraveStone(p);
break;
case 3:
blessGraveStone(p);
break;
case 4:
demolishGraveStone(p);
break;
}
}
private void degradeGraveStone() {
if (currentGrave < 6603) {
graveStoneDegrade(currentGrave + 1);
} else {
demolishGraveStone(player);
return;
}
setName(player.getDisplayName()+ "'s Gravestone");
player.sm("Your gravestone slighlty degrades, you have" + minutes + " minutes to get your items back!");
}
private void demolishGraveStone(Player p) {
if (player != p) {
p.sm("You cannot destroy a grave that isn't yours!");
return;
}
player.sm("Your gravestone has been destroyed.");
player.sm("Your items have been added to your bank.");
for (Item item : container)
player.getBank().addItem(item.getId(), item.getAmount(), true);
finish();
}
private void blessGraveStone(Player p) {
if (p.getSkills().getLevel(Skills.PRAYER) < 90){
p.sm("You need a prayer level of at least 90 to bless this Grave Stone.");
return;
}
p.sm("You bless " + player.getDisplayName() + "'s Grave Stone.");
player.sm(p.getDisplayName() + " has blessed your GraveStone.");
graveStoneDegrade(6601);
setName(player.getDisplayName()+ "'s Gravestone");
BEGIN_TIME = System.currentTimeMillis();
}
private void repairGraveStone(Player p) {
if (p.getSkills().getLevel(Skills.CRAFTING) < 75){
p.sm("You need a crafting level of at least 75 to repair this Grave Stone.");
return;
}
p.sm("You repair " + player.getDisplayName() + "'s Grave Stone.");
player.sm(p.getDisplayName() + " has repaired your GraveStone.");
graveStoneDegrade(this.getId() - 1);
setName(player.getDisplayName()+ "'s Gravestone");
BEGIN_TIME = System.currentTimeMillis();
}
private void sendMemorial(Player p) {
p.getInterfaceManager().sendInterface(INTERFACE);
p.getPackets().sendIComponentText(INTERFACE, 16, getName());
}
public Player getPlayer() {
return player;
}
}
I made this quick and easy. Feel free to use it!
TimerID's are used to indicate which timer was the one that stopped, incase you want to have more than one timer. The GameTimerListener interface has two methods.
public interface GameTimerListener {
public void SuccessfullStop(int TimerID);
public void AbortedStop(int TimerID);
}
This is the GameTimer class.
public class GameTimer implements Runnable{
private Thread TimerThread = new Thread(this);
private List<GameTimerListener> Listeners = new ArrayList<GameTimerListener>();
public static final int Seconds = 0,Minutes = 1,Hours = 2;
private int TimerID;
private int TimerSeconds;
private int Timeout = -1;
private boolean Ticking;
private boolean Paused;
public GameTimer(int TimerID){ this.TimerID = TimerID; }
public GameTimer(int TimerID,int SecondsToRun){ this.TimerID = TimerID; Timeout = SecondsToRun; }
public void run(){
long Timer = System.currentTimeMillis();
long LastTime;
try{
while(Ticking){
LastTime = System.nanoTime();
if((System.currentTimeMillis() - Timer) >= 1000){
Timer+= 1000;
if(!Paused){
TimerSeconds++;
}
if((Timeout - TimerSeconds) <= 0){
SuccessfullStop();
break;
}
}
Thread.sleep(10);
}
}catch(Exception e){ e.printStackTrace(); }
}
private int[] TimeLeftGetter(){
int Seconds = (Timeout - TimerSeconds);
int Minutes = 0;
int Hours = 0;
for(int x = 0; x < (Timeout - TimerSeconds); x++){
if(Seconds > 60){
Minutes++;
Seconds -= 60;
if(Minutes >= 60){
Hours++;
Minutes -= 60;
}
}
}
Seconds = Seconds <= 0 ? 0 : Seconds;
return new int[]{Seconds,Minutes,Hours};
}
public synchronized void start(){
if(Timeout == 0){ return; }
if(Ticking){ ForceStop(); }
TimerSeconds = 0;
Ticking = true;
TimerThread = new Thread(this);
TimerThread.start();
}
public void ForceStop(){
try{
Ticking = false;
TimerThread.join();
for(GameTimerListener rtl : Listeners)
rtl.AbortedStop(TimerID);
}catch(Exception e){ e.printStackTrace(); }
}
public String getTimeLeftByString(){
String time = "";
int[] Time = TimeLeftGetter();
time = Time[Hours] + ":" + Time[Minutes] + ":" + Time[Seconds];
return time;
}
public boolean TimeOver(){
if((Timeout - TimerSeconds) <= 0) {
return true;
}
return false;
}
private void SuccessfullStop(){
Ticking = false;
for(GameTimerListener rtl : Listeners)
rtl.SuccessfullStop(TimerID);
}
public void setTimeToStop(int Seconds){
Timeout = Seconds;
if(Ticking){ start(); }
}
public void addGameTimerListener(GameTimerListener rtl){
if(!Listeners.contains(rtl))
Listeners.add(rtl);
}
public void Remove(GameTimerListener rtl){
if(Listeners.contains(rtl))
Listeners.remove(rtl);
}
public int getTimerID(){ return TimerID; }
public int getSecondsToRun(){ return Timeout; }
public int[] getTimeLeftByInteger(){ return TimeLeftGetter(); }
public boolean NeverStops(){ return Timeout <= -1 ? true : false; }
public boolean Ticking(){ return Ticking; }
public void setPaused(boolean Value){ Paused = Value; }
}
This is how you would go and implement this.
On your gravestone class, let it implement GameTimerListener.
public class Gravestone extends NPC implements Serializable, GameTimeListener {
The two methods you will use are SuccessfullStop(int TimerID):void; and AbortedStop():void;
In the method SuccessfullStop is where you will put your code for when the time is up.
Now, lets say you want to create a new Timer that runs for five minutes. This is how you do it.
GameTimer MyTimer = new GameTimer(10,1500);
The first parameter is the ID of your timer.
I decided to give it 10 as the ID, because i like the number 10.
The second parameter is how long it will run in seconds.
1500 seconds is 5 minutes.
Before you start it or anything, be sure to add the gravestone class as a listener.
MyTimer.addGameTimerListener(this);
Now, whenever you want to start the timer, just call the method:
MyTimer.start();
This will do all the work for you.
When the timer reaches 0, it will call your SuccessfullStop() method.
Now, what if you were to use two timers? Thats where the TimerID comes in use.
When the SuccessfullStop() method gets called, note the Integer that gets passed as a parameter.
public void SuccessfullStop(int TimerID){
if(TimerID == MyTimer.getTimerID()){
//If the timer that stopped was MyTimer..
//Code goes here for your desired timer.
}
}
Hope I explained myself well. If you still have any questions, feel free to ask!