繁体   English   中英

如何为javax.swing.Timer编写Scala包装器

[英]How to write a Scala wrapper for javax.swing.Timer

我想在Scala Swing应用程序中使用计时器。 我可以使用Java版本,只是这意味着我必须实现ActionListener接口。 我宁愿使用Scala Publishers / Reactors模型来保持一致性,所以我可以把东西listenTo计时器。

这是我试过的:

class ScalaTimer(time: Int) extends Component {
  val t = new javax.swing.Timer(time, new java.awt.event.ActionListener {
    def actionPerformed(e: java.awt.event.ActionEvent) {
      publish(new scala.swing.event.ActionEvent(this))
    }
  })
  def start() {t.start()}
  def stop() {t.stop()}
  // etc

}

不起作用,因为this指的是ActionListener而不是ScalaTimer类。

另外我可能不应该扩展Component ...我试过这个因为我得到了Publisher / Reactor功能,但它没有用。 我应该这样做吗? 如果是这样,我是否还需要包含其他特征,如何知道我必须实施哪些方法?

 class ScalaTimer extends javax.swing.Timer with Publisher {

(我的IDE立即标记“缺少方法Timer(Int,ActionListener)的参数”,这似乎有点奇怪,因为我没有调用方法。)

这样做的规范方法是在你要引用的东西的顶部引入一个别名(通常是self除非已经采用):

class ScalaTimer(time: Int) extends Component {
  self =>
  val t = ...
    publish(new scala.swing.event.ActionEvent(self))
  ...

不起作用,因为它指的是ActionListener而不是ScalaTimer类。

汤姆是对的:你可以使用ScalaTimer.this

(我的IDE立即标记“缺少方法Timer(Int, ActionListener) ”,这似乎有点奇怪,因为我没有调用方法。)

Timer(Int, ActionListener)是的构造Timer ,你已经调用。 您需要编写extends javax.swing.Timer(constructor_args) 当然,构造函数参数可能依赖于ScalaTimer构造函数参数。

你可以用Java实现这一点:ScalaTimer.this

在Scala中它可能是相同的

我最近也必须解决这个问题,这似乎对我有用:

// First create a TimerEvent since using an ActionEvent necessitates that ScalaTimer extend
// Component, which isn't ideal as the OP indicated 
case class TimerEvent() extends scala.swing.event.Event

// extending javax.swing.Timer by and large avoids the hassle of writing wrapper methods
class ScalaTimer(val delay0:Int) extends javax.swing.Timer(delay0, null) with Publisher {

  // to mimic the swing Timer interface with an easier-to-user scala closure
  def this(delay0:Int, action:(()=>Unit)) = {
    this(delay0)
    reactions += {
      case TimerEvent() => action()
    }
  }

  addActionListener(new java.awt.event.ActionListener {
    def actionPerformed(e: java.awt.event.ActionEvent) = publish(TimerEvent())
  })
}

您还可以覆盖其他方法以提供更好的封装,但这是实用的。

简单的包装:

import scala.swing.event.Event,
       scala.swing.Reactions,
       java.awt.event.ActionEvent,
       javax.swing.AbstractAction


case class Tick(source: Timer) extends Event
case class Timeout(source: Timer) extends Event

abstract class Timer {
  private val timer = this
  private var counter = 0
  private val tick = new AbstractAction(){def actionPerformed(e:ActionEvent) = {
    reactions(Tick(timer))
    if(_repeats > 0){
      counter -= 1
      if(counter == 0){run = false; reactions(Timeout(timer))}}}}
  val reactions: Reactions = new Reactions.Impl
  private var _interval = 1000
  def interval:Int = _interval
  def interval_=(i:Int):Unit = {_interval = i; peer.setDelay(i)}
  private var _repeats = -1
  def repeats:Int = _repeats
  def repeats_=(i:Int):Unit = {_repeats = i; counter = i}
  private var _run = false
  def run:Boolean = _run
  def run_=(f:Boolean):Unit = { _run = f; runStop(f)}
  private def runStop(f:Boolean) = f match{
    case true => {
      counter = _repeats
      if(counter != 0){peer.start()}else{reactions(Timeout(timer))}}
    case false => peer.stop()}
  val peer = new javax.swing.Timer(_interval, tick); peer.setRepeats(true)}

采用:

import scala.swing._

object Main extends Frame {
  //
  override def closeOperation() = {System.exit(0)}
  visible = true
  //
  def main(a:Array[String]):Unit = {
    val t = new Timer{
      interval = 500 //In milliseconds
      repeats = 10   //Repeats 10 times
      reactions += {case Tick(_) => println("tick")
                    case Timeout(_) => println("timeout")}
      run = true}}}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM