setTimeout() approach

edited May 2015 in JavaScript Mode

Hey everyone, I wanted to share something I'm working on, but could use some help figuring out one piece of it.

As a Javascript guy I'm really used to using setTimeout(), and find it hard to work through the draw() approach to Processing using the millis() - prevMillis > interval approach, especially when I need to fire off a lot of timers.

So I made a class called SetTimeout(millisAtStart, interval, "func").

In the main file I have an ArrayList where I add to this and remove when finished in the draw() loop.

The piece I can't figure out, because it's Java is the callback function part.

Happy to share the code, but curious if anyone has any immediate feedback regarding the callback function.

Answers

  • Use the well known command pattern:

    interface Command
    {
      void execute();
    }
    void setup()
    {
    ArrayList<Command> commands = new ArrayList<Command>();
    commands.add(new Command() { public void execute() { println("First"); } });
    commands.add(new Command() { public void execute() { println("Other"); } });
    
    for (Command command : commands)
    {
      command.execute();
    }
    exit();
    }
    

    Of course, the execute method can be defined to take parameters and to return something, if you need to.

  • edited May 2015

    I was wondering the same thing recently and ended up using a wee bit of reflection and a separate thread. Here's a very basic example:

    The main tab:

    float bg;
    
    void setup(){
      setTimeout("test",2000);
      setInterval("tick",1000);
    }
    void draw(){
      background(bg);
    }
    void test(){
      println("test");
    }
    void tick(){
      bg = random(255);
    }
    void mouseReleased(){
      clearInterval("tick");
    }
    

    a separate tab I called Utils:

    void setTimeout(String name,long time){
      new TimeoutThread(this,name,time,false);
    }
    void setInterval(String name,long time){
      intervals.put(name,new TimeoutThread(this,name,time,true));
    }
    void clearInterval(String name){
      TimeoutThread t = intervals.get(name);
      if(t != null){
        t.kill();
        t = null;
        intervals.put(name,null);
      }
    }
    HashMap<String,TimeoutThread> intervals = new HashMap<String,TimeoutThread>();
    
    import java.lang.reflect.Method;
    
    class TimeoutThread extends Thread{
      Method callback;
      long now,timeout;
      Object parent;
      boolean running;
      boolean loop;
    
      TimeoutThread(Object parent,String callbackName,long time,boolean repeat){
        this.parent = parent; 
        try{
          callback = parent.getClass().getMethod(callbackName);
        }catch(Exception e){
          e.printStackTrace();
        }
        if(callback != null){
          timeout = time;
          now = System.currentTimeMillis();
          running = true;  
          loop = repeat; 
          new Thread(this).start();
        }
      }
    
      public void run(){
        while(running){
          if(System.currentTimeMillis() - now >= timeout){
            try{
              callback.invoke(parent);
            }catch(Exception e){
              e.printStackTrace();
            }
            if(loop){
              now = System.currentTimeMillis();
            }else running = false;
          }
        }
      }
      void kill(){
        running = false;
      }
    
    }
    

    It calls functions in your sketch by passing a string containing their name. You don't need to keep track of intervals as you would normally in javacript, you just need to pass the name of the function the interval called.

    This is a basic approach and has it's limitations. For example you can't use arguments/parameters with the functions at the moment.

    HTH, George

  • This is great, thanks George! Obviously the lack of arguments/param is a slight issue, but great start!

Sign In or Register to comment.