我正在学习使用显示时间减少的 GUI 实现倒数计时器。我正在使用Groovy的@Bindable,希望时间减少的变化可以自动显示在相应的UI标签中。
倒计时时间值的减少是在定时器线程中完成的,与 UI 线程分开。但是,倒数计时器不会在 UI 中更新。
正确更新 UI 中的倒计时时间的适当方法是什么?
import groovy.swing.SwingBuilder
import java.awt.FlowLayout as FL
import javax.swing.BoxLayout as BXL
import javax.swing.JFrame
import groovy.beans.Bindable
import java.util.timer.*  
// A count-down timer using Bindable to reflcet the reduction of time, when the reduction is done in a TimerTask thread
class CountDown {
  int delay = 5000   // delay for 5 sec.  
  int period = 60*1000  // repeat every minute.  
  int remainingTime = 25*60*1000
  // hope to be able to update the display of its change:
  @Bindable String timeStr = "25:00"
  public void timeString () {
    int seconds = ((int) (remainingTime / 1000))  % 60 ;
    int minutes =((int) (remainingTime / (1000*60))) % 60;
    timeStr = ((minutes < 9) ? "0" : "") + String.valueOf (minutes)  + ":" + ((seconds < 9) ? "0" : "") + String.valueOf (seconds)
  }
  public void update () {
    if (remainingTime >= period)
      remainingTime =  (remainingTime - period)
    // else // indicate the timer expires on the panel
    // println remainingTime
    // convert remainingTime to be minutes and secondes
    timeString()
    println timeStr // this shows that the TimerTaskCountDown thread is producting the right reduction to timeStr
  }
}
model = new CountDown()
class TimerTaskCountDown extends TimerTask {
  public TimerTaskCountDown (CountDown modelIn) {
    super()
    model = modelIn
  }
  CountDown model
  public void run() {
    model.update() // here change to model.timeStr does not reflected
  }  
}  
Timer timer = new Timer()  
timer.scheduleAtFixedRate(new TimerTaskCountDown(model), model.delay, model.period)
def s = new SwingBuilder()
s.setVariable('myDialog-properties',[:])
def vars = s.variables
def dial = s.dialog(title:'Pomodoro', id:'working', modal:true, 
                    // locationRelativeTo:ui.frame, owner:ui.frame, // to be embedded into Freeplane eventually
                    defaultCloseOperation:JFrame.DISPOSE_ON_CLOSE, pack:true, show:true) {
  panel() {
    boxLayout(axis:BXL.Y_AXIS)
    panel(alignmentX:0f) {
      flowLayout(alignment:FL.LEFT)
      label text: bind{"Pomodoro time: " + model.timeStr}
    }
    panel(alignmentX:0f) {
      flowLayout(alignment:FL.RIGHT)
      button(action: action(name: 'STOP', defaultButton: true, mnemonic: 'S',
                            closure: {model.timeStr = "stopped"; vars.ok = true//; dispose() // here the change to model.timeStr gets reflected in the label
                            }))
    }
  }
}