【问题标题】:How to write a Scala wrapper for javax.swing.Timer如何为 javax.swing.Timer 编写 Scala 包装器
【发布时间】:2011-07-26 05:40:56
【问题描述】:

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

这是我尝试过的:

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) 缺少参数”,这似乎有点奇怪,因为我没有调用方法。)

【问题讨论】:

标签: java swing scala timer wrapper


【解决方案1】:

执行此操作的规范方法是在您要引用的内容的顶部引入别名(通常是 self,除非已经采用):

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

【讨论】:

  • 似乎self 已经用于表示UIElementpeer,因此指的是java.awt.Component。如果我使用其他别名,则可以使用
  • @Luigi Plinge - 我通常在拍摄self 时使用outer
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

    您将能够在 Java 中实现这一点: ScalaTimer.this

    在 Scala 中可能是一样的

    【讨论】:

      【解决方案4】:

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

      // 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())
        })
      }
      

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

      【讨论】:

        【解决方案5】:

        简单的包装器:

        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}}}
        

        【讨论】:

          猜你喜欢
          • 2021-10-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-15
          相关资源
          最近更新 更多