如何使用Scala将侦听器添加到Javafx UI组件中



我正在使用scala和 Publisher特质来侦听我的数据组件上的更改,并发布/更新显示到swing ui component(如此)

我最近重写了我的程序以使用Javafx2Scala,并且我无法使用最近的绑定项目Scalafx,因为我的程序中只有某些部分切换到Javafx(已嵌入swing jframe)。

)。

我可以在Scala中使用的最佳语法具有基于Scala.swing Publisher特质的相同(或相似)行为?

您是否有一些链接或简单示例来说明此方法?

我目前可以提出的建议是重复使用scala.swing的模式,该模式实现了 publish/react/react 系统。可以从旧 scala.swing存储库中的scala.swing.com列出一个示例。

这个想法是为所有需要发布事件的所有 javafx 类创建最通用的包装器,并将这些类隐含地转换为此包装器。

包装器将从 javafx 侦听器 publish/react/react system。

示例代码看起来像这样,并且基于上述scala.swing代码

  package scala.fx.react
  object ScalaFxReactive {
      /*
       * Can't say if Node is the best and only class that should be converted.
       * You should make implicit publishers from any fx class that supports the
       * addEventHandler(someEventType)
       */
      implicit def toPublisher(peer: Node): ScalaFxComponentPublisher = new ScalaFxComponentPublisher(peer)
  class ScalaFxComponentPublisher(peer: Component) {
    /**
     * Contains publishers for various mouse events. They are separated for
     * efficiency reasons.
     */
    object mouse {
       /**
        * Publishes clicks, presses and releases.
        */
        val clicks: Publisher = new LazyPublisher {
          lazy val clicked = new EventHandler[MouseEvent] {
            def handle(e: MouseEvent) {
               /*
                *This is the most critical part: you need
                * to check if it's possible to create the swing 
                * event from an fx event, eventually through an
                * implicit conversion
                */
               publish(new MouseClicked(e))
            }
          }
          def onFirstSubscribe() = peer.setOnMouseClicked(clicked)
          def onLastUnsubscribe() = peer.setOnMouseClicked(null)
          /*
           * probably better:
           * def onLastUnsubscribe() = peer.removeEventHandler(MouseEvent.MOUSE_CLICKED)
           */
        }
        /**
         * Publishes enters, exits, moves, and drags.
         */
        val moves: Publisher = new LazyPublisher {
           lazy val entered = new EventHandler[MouseEvent] {
             def handle(e: MouseEvent) {
               publish(new MouseEntered(e))
             }
           }
           lazy val exited = new EventHandler[MouseEvent] {
             def handle(e: MouseEvent) {
               publish(new MouseExited(e))
             }
           }
           /*
            * Need implementation
            */
           lazy val moved = new EventHandler[MouseEvent] {
             ...
           }
           def onFirstSubscribe() {
             peer.setOnMouseEntered(entered)
             peer.setOnMouseExited(exited)
             ...
           }
           def onLastUnsubscribe() {
             peer.setOnMouseEntered(null)
             peer.setOnMouseExited(null)
             ...
           }
         }
       }
     }

然后,您可以像使用scala.swing

一样支持组件中的反应
class MyComponent {
    import scala.fx.react.ScalaFxReactive._
    listenTo(node)
    reactions += {
      ...   
    }
}

该代码将被视为粗略的草图,并且不会按原样编译。它指向可能的方向,但是完整的解决方案可能是一个足够有趣的库,对于像您一样,需要逐步将传统scala.swing应用程序桥接到javafx库。

最新更新