Wicket countdown timer will not self-update

梦想与她 提交于 2019-12-08 05:08:22

问题


I would like to implement a countdown timer in Wicket. I have a clock class:

public class Clock extends Label{
    private static int time;
    public Clock(int mytime,String id,String message){
    super(id,message);
        time=mytime;
        this.setDefaultModelObject(message);
    }

    public int getTimeLeft(){
        return time;
    }

    public void decrement(){
        time--;
    }
}

and here I attempt to update it every second:

clock.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(1)){
    protected void onTimer(AjaxRequestTarget target){
        clock.decrement();
        target.addComponent(clock);
    }           
});

This doesn't work because onTimer is a final method and therefore cannot be overridden. What is the correct approach?


回答1:


There are two problems here.

  1. Where does time appear in the generated label markup? The model simply contains the message so even if time is changed, it won't make any difference.
  2. As you mentioned, onTimer() is final, and even if it wasn't, there's no guarantee that it would be invoked precisely every second.

So the solution, as so often in Wicket is to turn it upside down, instead of pushing data into your output, let the framework pull it in. This is what you need to do.

  1. You don't need a separate Clock class, use just a plain Label with nothing overridden.
  2. Create an IModel<String> subclass that stores the timestamp when the clock should be at zero.
  3. Make the getObject() method of the model return a string that contains the difference between the clock's zero time and the current time.
  4. Set an instance of this as the model of your Label and add the ajax timer behaviour too.
  5. Done.

Your model will be something like this:

public class ClockModel implements IModel<String> {
    private long zeroTime;

    public ClockModel( int timeInSecs ) {
        this.zeroTime = System.currentTimeMillis() + (timeInSecs * 1000 );
    }

    public String getObject() {
        return String.valueOf( ( zeroTime - System.currentTimeMillis() ) / 1000 );
    }

}

You can probably guess the rest.

Update: just one more thing, kind of obvious but may be worth mentioning: in a real world application make sure you check that time left isn't negative.




回答2:


The other answer is best, but another alternative is to use an AbstractAjaxTimerBehavior, where the onTimer method is not final.

Look at the source code for the Wicket Stuff World Clock example and you'll see

    add(new AbstractAjaxTimerBehavior(Duration.seconds(1))
    {
        /**
         * @see org.apache.wicket.ajax.AbstractAjaxTimerBehavior#onTimer(org.apache.wicket.ajax.AjaxRequestTarget)
         */
        protected void onTimer(AjaxRequestTarget target)
        {
            target.addComponent(la);
            target.addComponent(ny);
            target.addComponent(moscow);
            target.addComponent(prague);
            target.addComponent(london);
        }
    });


来源:https://stackoverflow.com/questions/7032620/wicket-countdown-timer-will-not-self-update

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!