0

This post is related to my last post.The block of code changes the text to desired color after desired time. however, now I want to change the color of a perticular word such that each letter gets the equal time.EG if "hello" have been given a time of 1000 milliseconds (have 5 letters) then 'h''e''l''l''o' each letter should get 1000/5 milliseconds i.e 200 milliseconds each.

I implemented swing timer for this :

public Reminder() {

    a[0]=2000;
    a[1]=1000;
    a[2]=3000;
   a[3]=5000;
    a[4]=3000;
ActionListener actionListener = new ActionListener() {
  public void actionPerformed(ActionEvent actionEvent) {
  point =point +arr[i].length();
i++;

     doc.setCharacterAttributes(0,point+1, textpane.getStyle("Red"), true);
     timer.setDelay(a[i]);

    }
};

timer = new Timer(a[i], actionListener);
timer.setInitialDelay(0);
timer.start();

For this to happen, shoud I use another Timer inside the actionListener to give further timings to a perticular letter?Or should I first break the time by .length() and then use the timer?I cannot decide a better way.Any ideas?

Community
  • 1
  • 1
joey rohan
  • 3,505
  • 5
  • 33
  • 70

1 Answers1

1

You should never need more than one timer. Since you know ahead of time exactly when everything should happen, just calculate those times, put them in a list (sorted by time) and execute each one.

public colorize(int offset, int length) {
    long triggerTime[] = new long[length];
    long startTime = System.currentTimeMillis();
    for (int i=0; i<length; i++) {
         triggerTime[i] = startTime + (1000*i)/length;
    }

    for (int i=0; i<length; i++) {
        //just wait for the next time to occur
        Thread.sleep(triggerTime[i]-System.currentTimeMillis());
        doc.setCharacterAttributes(offset, i+1, textpane.getStyle("Red"), true);
    }
}

This may strike you as very pedestrian because it does not use a TimerTask object, but it is effective, efficient, and easy to debug. You simplty call this method on whatever thread you want, and it occupies the entire thread, and the word will be colorized at a rate such it is completed in 1 second.

You could, if you don't have a thread handy, make a timer that calls this, but the only reason for that is to access a thread. The real point is: don't set up multiple timers, just make an array of time values. After one event is satisfied, set to delay until the next time. You never need multiple timers.

It would be a little cleaner if you made an object that represented the coloring of a character (or whatever action you want) and you put together a collection of these actions. Then sort the entire collection by time they are to go off. The loop above would walk through the collection, waiting until the time for the action arrives, and then executing it. Another advantage of this approach is that you could clear the collection and that would terminate the loop.

See the discussion of the overuse of timers on my website to understand why this is bad.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
AgilePro
  • 5,588
  • 4
  • 33
  • 56