2013-10-15 87 views
0

基於紙張Deprecating the Observer Pattern with Scala.React我試圖從紙建立一個簡單的例子,但它扔一個異常Exception in thread "main" java.lang.AssertionError: assertion failed: This method must be run on its domain [email protected]斯卡拉簡單示例陣營

一個相關的問題是Running a simple Scala.React expression

如何設置所有使用scala反應庫的強大功能?

除了庫scala-react,我用下面的例子:

object MyFirstReact extends App { 

    object MyDomain extends scala.react.Domain { 
    protected val scheduler: Scheduler = new ManualScheduler 
    protected val engine: Engine = new Engine 
    } 
    import MyDomain._ 

    case class MouseEvent(position: (Int, Int)) 
    class Path(var positions: Seq[(Int, Int)]) { 
    def this(pos: (Int, Int)) = this(Seq(pos)) 
    def lineTo(pos: (Int, Int)) { positions = positions :+ pos } 
    def close { positions = positions :+ positions.head } 
    } 

    val mouseDown: Events[MouseEvent] = Events.once(MouseEvent((0, 0))) 
    val mouseMove: Events[MouseEvent] = Events.once(MouseEvent((1, 1))) 
    val mouseUp: Events[MouseEvent] = Events.once(MouseEvent((2, 2))) 
    def draw(path: Path) { /* ... */ } 

    Reactor.loop { self => 
    // step 1 
    val path = new Path((self await mouseDown).position) 
    self.loopUntil(mouseUp) { // step 2 
     val m = self awaitNext mouseMove 
     path.lineTo(m.position) 
     draw(path) 
    } 
    path.close // step 3 
    draw(path) 
    } 

} 

回答

1

你得到了異常,因爲Reactor.loop必須與調度{...}塊包裹。但修復這是不夠的(我有一個java.lang.StackOverflowError)。

無論如何,我準備了一個使用scala-swing的完整工作示例,其中您可以使用與您擁有的相同反應器代碼實際繪製一條線。我把一個sbt可構建的副本與scala反應包括到github:https://github.com/zsoltdonca/scala-react-line-drawing

package zsd 

import scala.swing._ 
import java.awt.event.{MouseMotionAdapter, MouseEvent, MouseAdapter} 
import java.awt.{Color, Point} 
import scala.react.Domain 

object MyDomain extends Domain { 
    val scheduler = new SwingScheduler() 
    val engine = new Engine 
} 

import MyDomain._ 

object ScalaReactLineDrawing extends SimpleSwingApplication with Observing { 

    override def main(args: Array[String]) { 
    schedule { startup(args) } 
    start() // starts the scala-react engine 
    } 

    override def top: Frame = new MainFrame() { 
    contents = new FlowPanel() { 
     val mouseDown = EventSource[Point] 
     val mouseMove = EventSource[Point] 
     val mouseUp = EventSource[Point] 

     val mainProgramFlow = Reactor.loop { 
     self => 
     // step 1 
      val path = new Path(self await mouseDown) 
      self.loopUntil(mouseUp) { 
      // step 2 
      val m = self awaitNext mouseMove 
      path.lineTo(m) 
      draw(path) 
      } 
      path.close() // step 3 
      draw(path) 
     } 

     peer.addMouseListener(new MouseAdapter { 
     override def mousePressed(e: MouseEvent): Unit = mouseDown << e.getPoint 
     override def mouseReleased(e: MouseEvent): Unit = mouseUp << e.getPoint 
     }) 
     peer.addMouseMotionListener(new MouseMotionAdapter { 
     override def mouseDragged(e: MouseEvent): Unit = mouseMove << e.getPoint 
     }) 

     class Path(var positions: Seq[Point]) { 
     def this(pos: Point) = this(Seq(pos)) 

     def lineTo(pos: Point) { 
      positions = positions :+ pos 
     } 

     def close() { 
      positions = positions :+ positions.head 
     } 
     } 

     var pathDrawn = new Path(new Point(0, 0)) 
     def draw(path: Path) { 
     pathDrawn = path 
     repaint() 
     } 

     override protected def paintComponent(g: swing.Graphics2D): Unit = { 
     super.paintComponent(g) 

     val xPoints = pathDrawn.positions.map(pos => pos.x).toArray 
     val yPoints = pathDrawn.positions.map(pos => pos.y).toArray 
     g.setColor(Color.BLACK) 
     g.drawPolyline(xPoints, yPoints, pathDrawn.positions.length) 
     } 
    } 
    preferredSize = new Dimension(400, 300) 
    pack() 
    } 
}