0

Just have a look on this block of code:

public Reminder() {

    a[0]=1000;
    a[1]=3000;
    a[2]=1000;
   a[3]=5000;
    timer = new Timer();

  timer.schedule(new RemindTask(),0,  a[i]);

  }
 //////////////////////
   class RemindTask extends TimerTask  {

    public void run() {

  point =point +arr[i].length();

     doc.setCharacterAttributes(0,point+1, textpane.getStyle("Red"), true);
     i++;

    }
    }

I want delay to be changed after each task,so the timings are stored in an array. When i++ is preformed(pointer to array),the timings are not changed;the subsequent rate of delay is same as the first delay value.Why it dosn't change?

EDIT:

Here's an SSCCE if required:

import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;


public class Reminder {
static   JFrame frame;
Toolkit toolkit;
Timer timer;
int point=0;
static   StyledDocument doc;
 static   JTextPane textpane;
 String[] arr={"Tes"," hiiii"," what"," happpn"};
public int i=0;
long[] a=new long[4];
public Reminder() {

    a[0]=1000;
    a[1]=3000;
    a[2]=1000;
   a[3]=5000;
    timer = new Timer();

  timer.schedule(new RemindTask(),0,  a[i]);

 }

 class RemindTask extends TimerTask  {

    public void run() {

  point =point +arr[i].length();

     doc.setCharacterAttributes(0,point+1, textpane.getStyle("Red"), true);
     i++;


    }
  }
 public static void newcompo()
{

    JPanel panel = new JPanel();
    doc = (StyledDocument) new DefaultStyledDocument();
  textpane = new JTextPane(doc);
    textpane.setText("Test hiiii what happpn");
    javax.swing.text.Style style = textpane.addStyle("Red", null);
    StyleConstants.setForeground(style, Color.RED);
           panel.add(textpane);
    frame.add(panel);
    frame.pack();

 }
  public static void main(String args[]) throws InterruptedException,   InvocationTargetException {
      SwingUtilities.invokeAndWait(new Runnable() {

        public void run() {
            frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            frame.setVisible(true);

           newcompo();
        }
    });



 Reminder aa=  new Reminder();

  }
 }
joey rohan
  • 3,505
  • 5
  • 33
  • 70

4 Answers4

4

When using Swing, better to use javax.swing.Timer over javax.util.Timer. That will give you the setDelay method:

timer = new Timer(0, new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        if (i > a.length) { // check when to stop
            timer.stop();
            return;
        }

        point = point + arr[i].length();
        doc.setCharacterAttributes(0, point + 1, textpane.getStyle("Red"), true);
        i++;

        // Change delay period
        timer.setDelay(a[i]);
    }
});
timer.setDelay(a[0]);
timer.start();

This will required you to change the type of your delay array a, from

long[] a = new long[4];

to this:

int[] a = new int[4];
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • +1 yup the way to go, and not only will it give `setDelay` the document will be updated on EDT, which is best practice – David Kroukamp Jan 06 '13 at 16:27
  • Wanted an answer without Swing timers.My EDT is safe. – joey rohan Jan 06 '13 at 17:56
  • Well, this is confusing.I still believe, my last question was worth asking.Anyways,any solution w.r.t util timers? – joey rohan Jan 06 '13 at 18:06
  • I would recommend to go with `javax.swing.Timer`. You need very few changes & I've given you most of what you need here. – Reimeus Jan 06 '13 at 18:21
  • @joeyrohan Reimeus is correct, `javax.swing.Timer` is much simpler solution. If you really want to use `java.util.Timer` instead, then you MUST resync any updates to the UI with the EDT within the timer's `run` method using `SwingUtilities.invokeLater` – MadProgrammer Jan 06 '13 at 23:13
  • Yeah,I did that,its working fine now.thanks @Reimeus .Its smooth and easy. – joey rohan Jan 07 '13 at 11:05
0

Try with declaring the variable i as volatile.

SylvainL
  • 3,926
  • 3
  • 20
  • 24
  • Done,but nothing happened.But why volatile?Its just a cpu thing,what change can it bring? – joey rohan Jan 06 '13 at 15:52
  • When you need to read the same mutable variable from different thread, this variable should be declared as volatile; otherwise, it's possible to change its value while the other thread(s) will kept reading the old value. This is an optimization thing. In your case, if this is not the solution then it appears that possibly we don't have enough information to find where the bug is. – SylvainL Jan 06 '13 at 15:55
  • I have given an SSCCE.Well,the value of i is changed,but not the delay time. – joey rohan Jan 06 '13 at 15:58
0

Into your run(), you need to cancel the old timer and re-run a new one, something like (untested):

public void run() {
   ...
timer.cancel(); // Terminate the timer thread.
timer = new Timer();
timer.schedule(new RemindTask(), 0, a[i]);
}

And of course, it's probably better to specify the initial delay instead:

timer.schedule(new RemindTask(), a[i]);
SylvainL
  • 3,926
  • 3
  • 20
  • 24
0

A second method would be to schedule your run() every second but return without doing nothing when it's not the time to perform the next action.

SylvainL
  • 3,926
  • 3
  • 20
  • 24