I'm trying to implement a very simple stopwatch widget in my Android activity such that the user can hit start/reset to start the timer, and stop to stop it. All of the functionality is there, but I can't seem to find a way to constantly display the value of this stopwatch.
I'm currently using a custom object that stores a long value representing the time the Stopwatch object was created, a constructor that sets this long value to the current time, and a displayTime method that returns the a double value representing the current time in seconds by subtracting the current time from the original time and divides by 1000.0.
Like I said, functionally it's flawless, but I can't see a way to constantly update a TextView object with the value of displayTime(). Can anyone suggest as simple of a solution as possible to accomplish this? Thank you!
You need to use Timer class for this purpose.
ActionListener timerTask = new ActionListener() {
public void actionPerformed(ActionEvent e) {
lblTime.setText("Set your time here");
}
};
Timer timer = new Timer(500, timerTask);
timer.start();
For Timer Class Information and API
Class Timer API
How to Use Swing Timers
The easiest way is probably to use a Handler.
private Handler h = new Handler();
private Runnable update = new Runnable() {
void run() {
// update the time in the text view here
h.postDelayed(this, 1000); // reschedule the update in 1 sec
}
};
// to start the update process
h.postDelayed(update, 0); // run the update the first time
Related
In essence, I have an onGuildMessageReceived method that listens for a command alarm with which a user can set a countdown to notify him with a message. They type a time amount and eventual alarm message that comes with the ping they will get after that time.
My question is, how can I make this feature work for each user separately, so other users don't overwrite previous alarm times that were already ticking?
This method is called in the main code to start the countdown.
public void StartTimer(int seconds, GuildMessageReceivedEvent event)
{
timer = new Timer();
timer.schedule(new TimerReminder(event), seconds * 1000);
}
public void StartTimer(int seconds, GuildMessageReceivedEvent event, String text)
{
timer = new Timer();
timer.schedule(new TimerReminder(event, text), seconds * 1000);
}
I have this subclass that does a block of code after the .schedule() time.
class TimerReminder extends TimerTask{
GuildMessageReceivedEvent eventtrigger;
String alarmText = "";
private TimerReminder(GuildMessageReceivedEvent event)
{
eventtrigger=event;
}
private TimerReminder(GuildMessageReceivedEvent event, String alarmArg)
{
eventtrigger=event;
alarmText=alarmArg;
}
public void run()
{
if(alarmText.isEmpty())
{
eventtrigger.getChannel().sendMessage("<#"+auth+">, ***your alarm is ringing!***🔔🔔🔔🔔").queue();
timer.cancel(); // Terminate the timer thread
}
else
{
eventtrigger.getChannel().sendMessage("<#"+auth+">:\n"+alarmText).queue();
timer.cancel(); // Terminate the timer thread
alarmText="";
}
}
}
At the end of each task, you're running cancel on the timer reference which cancels not the timer that is currently running (Unless no one else ran the command) but rather the timer object that is assigned at the moment to the timer reference which makes it seem like the timers are overwriting each other.
And even if you kept a reference to all of the timers so you could cancel them, there's no need for you to cancel the timer after the task completes, the timer terminates itself.
Furthermore, there's no need for you to keep a static reference to the timer that is currently running, or keep a reference to them at all. When you create a timer a background thread keeps a reference to the timer and the task so they won't get garbage collected. You'd be better off creating the timer as a local variable when the command is run, scheduling the timer and that's it.
If you want the ability to cancel the timers by a different command or whatever you have in mind, then you should keep a list or map with references to all the current timers so you can cancel them if needed.
I'm creating a java paint program and can't figure out how to implement a timer that starts when the GUI is opened so the user can see their time spent drawing so far. My code is pasted below. I'm a complete beginner and have searched all the oracle documents and can't understand them so any help is appreciated! Hopefully there's a simple way of implementing this.
I added a JLabel onto my toolbar so I can try and post the "Drawing Time: "+totalTime but it stays at 0 for some reason I don't know how to make it refresh every second...
I would try something like this:
Set up the Global Variables (Make sure you fix your imports)
public class MainWindow extends javax.swing.JFrame implements ActionListener{
//global variable for tracking time
Timer timer;
final int DELAY = 1000; //the delay for the timer (1000 milliseconds)
int myCounter;
then initialize the timer and counter and make sure to send the info from the counter to your label
public MainWindow() {
initComponents();
//initialize the timer and the counter
timer = new Timer(DELAY, this);
timer.start();
myCounter = 0;
}
//method needed for the timer, since this class implements ActionListener
//this method will get called however often the DELAY is set for
#Override
public void actionPerformed(ActionEvent e){
myCounter++;
labelOutput.setText(Integer.toString(myCounter));
}//end of method
This is a pretty basic example of setting up a timer, so if you just apply the steps taken in the code I've given you to your own application, you'll probably be able to get it working. Good luck!
So I looked at so many sources and whenever there is such a problem, it's because the countdowntimer is trying to get cancelled from inside the ontick. This is not my issue. I have the countdowntimer in a runnable. I cancel the timer, I cancel the runnable and it still somehow gets called. Here is some code below. I appreciate any help!
Handler myHandler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
CountDownTimer countdownTimer = new CountDownTimer(difference - (1000 * 60) + 2000, 60000) {
public void onTick(long millisUntilFinished) { // some work here
}
public void onFinish() {
// some other work here
};
data.get(i).setCountDownTimer(countdownTimer);
data.get(i).getCountDownTimer().start();
}
};
data.get(i).setHandler(myHandler);
data.get(i).setRunnable(runnable);
data.get(i).start(2000);
The start function is basically:
public void start(int milliseconds){
handler.postDelayed(runnable, milliseconds);
}
data is just a list of objects where each has its own runnable, handler and countdowntimer.
Here is what I do when I cancel:
data.get(i).getCountDownTimer().cancel();
data.get(i).terminate();
The terminate function is basically:
public void terminate() {
handler.removeCallbacks(runnable);
}
Someone please tell me why the countdowntimer somehow still runs after I cancel it the way I do above; thanks!
UPDATE
In onFinish, I have another countdown that is on a smaller interval. Is onFinish called when I cancel a CountDownTimer? Otherwise I'm really out of ideas! Thanks.
Although you made a good effort to post the relevant pieces of your code, I'm having a hard time imagining how they all fit together. For example, when you create the Runnable for each data object, are the calls to set and start the countdown timer really in the run() method as shown? I'm wondering how data and i are accessible at that point. And if they are truly accessible, how you know that i will have the desired value when the Runnable comes out of the queue and executes?
I agree that cancel() should cause the CountDownTimer to stop. Note however that if start() is called after cancel() the timer will start anew--it's not a one-shot. If a bug is causing start() to be called a second time, it will look like the cancel didn't work.
All I can suggest is that you add a bunch of Log statements throughout your code to confirm your assumptions about when timers are starting and being cancelled, and what the value of i is for each instance.
This was a very silly mistake on my end. When I was removing an object from the data list, I was cancelling the alarm via:
data.get(i).getCountDownTimer().cancel();
And then I remove the object, and notifyitemremoved. The mistake is that I should notifyitemchanged, and in the onbind, I should cancel it. Then I should remove the entry safely knowing the CTD has been cancelled. Anyway, thanks everyone for the input.
I need a way to have a timer that is running on start command. Initially, the timer will be told how long to run for. However, i need a way to change this mid-way in between. If a user specifies that they would like to change the time the timer runs (by either decreasing, increasing or even ending the timer all together). I also want to be able to update the UI by showing the current time in minutes:seconds format.
The user may also want to spawn multiple timers - so they should have a way of monitoring and accessing different timers which they have set..
Currently this is what i have - from what i can tell, it works.. but i don't feel too good about it :S how can i make this better? Or what is the right way of doing this? Keep in mind that there will be other things happening while this timer is running - for instance, the user may be interacting with the UI and executing different commands un-related to the timer..
I really don't know much about threads or threading... so this is relatively new to me..
thanks in advance!
In Main:
//every time they request for a new timer, i will instantiate a new Task object..
Task task = new Task();
task.run()
task.getTaskTime();
Task.java:
public class Task extends Thread{
#Override
public void run()
{
timer = new Timer(60 * 60);
timer.start();
}
public boolean getTImerRunning() {
return timer.timerRunning;
}
public double getTaskTime() {
return timer.currentTime;
}
}
In Timer.java:
public class Timer extends Thread {
public static final int DEFAULT_TIMER = 180;
private long startMinute = 0;
private int _timer;
public double currentTime = 0;
public boolean timerRunning = true;
Timer(int timer) {
this._timer = timer;
}
Timer() {
this._timer = DEFAULT_TIMER;
}
#Override
public void run(){
long start = System.currentTimeMillis();
startMinute = start;
while(elapsedTime() <= this._timer) {
currentTime = elapsedTime();
}
timerRunning = false;
}
/**
* Return elapsed time since this object was created.
*/
private double elapsedTime() {
long now = System.currentTimeMillis();
return (now - startMinute);
}
}
Every time the user creates a "timer", do not create a new Task, but create an object MyTimer that holds the creation time and countdown duration and add the instance to an ArrayList.
The very first and only the first time, a user creates a timer you will create a task that executes every second. When that task executes it updates the UI and cycles through the ArrayList and updates each instance of MyTimer by adjusting the countdown duration.
That should keep things simple and reduce overhead.
Good Luck!
After creating a session, i want to call a method again & again after a specific time - i.e. 5 sec.
But when i call a method it gives me an error. Here is the sample code.
public class RunFunction extends MainScreen{
public RunFunction()
{
//Call Function again and again after 5 sec
setTitle("Timer");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
BasicEditField b = new BasicEditField("Hello", "");
String a = b.getText();
Dialog.alert("Value " +a);
}
}, 5000);
}
}
I need help related to this. Can you provide any sample code?
From the BlackBerry docs on the Timer class:
A facility for threads to schedule tasks for future execution in a background thread.
So, the first thing to understand is that whatever work you do in the run() method will be run on a background thread. Background threads are not allowed to modify the UI directly. You're probably getting an IllegalStateException by doing that.
Maybe this is just test code, but this code
BasicEditField b = new BasicEditField("Hello", "");
String a = b.getText();
Dialog.alert("Value " +a);
is a little confusing. It creates a BasicEditField, but only uses it to get the String value passed in to it. Just instantiating a field does not add it to a screen. So, you would need to call
add(b);
after this code for the edit field to show. But again, that would be modifying the UI directly. So, in your case, you probably just need to wrap your code with a call to UiApplication#invokeLater():
timer.schedule(new TimerTask() {
public void run() {
// this code executed on background thread -> not UI safe!
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// this code safely executed on UI thread
BasicEditField b = new BasicEditField("Hello", "");
add(b);
String a = b.getText();
Dialog.alert("Value " +a);
}
});
}
}, 5000);
Next, calling Timer#schedule(TimerTask,long) will only schedule your task to run once, after 5000 milliseconds. If you want it to run again and again, use the version of schedule(TimerTask,long,long) that takes three parameters. The last parameter is the amount of time between each call to your timer task's run() method.
This example on Timer and TimerTask java class provides some insights on what you want to do:
http://javaprogramming.language-tutorial.com/2012/02/demonstrate-timer-and-timertask.html