How can you get ScalaFX to play well on the SBT console?

I am writing an image library for computer students to play with. (I stole the idea and templates from the image library for DrRacket.)

https://github.com/dupontmanualhs/dm-image

This is mainly written in Swing (this is the master branch), but I'm trying to convert it to ScalaFX (see the scalafx branch), and there are some problems. Ideally, the student should be able to do something like:

 scala> import org.dupontmanual.image._ scala> TrainEngine.display() 

and a dialog box appears with the train engine. I tried using code

https://github.com/scalafx/ScalaFX-Tutorials

in the stand-alone-dialog project, but if I turn on System.exit(0) after I have dialog.showAndWait() , I get this error:

 Not interrupting system thread Thread[process reaper,10,system] Exception while removing reference: java.lang.InterruptedException java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) at com.sun.glass.utils.Disposer.run(Disposer.java:69) at java.lang.Thread.run(Thread.java:744) Not interrupting system thread Thread[Prism Font Disposer,10,system] Exception in runnable Exception in thread "JavaFX Application Thread" 

(Note that I get the same error if I try to start the App from stand-alone-dialog in the console, so I assume that calling System.exit(0) not a great idea in the SBT console.)

If I leave the line System.exit(0) , then everything works fine - basically. After the dialog box first appears, this does not focus the dialog, so I have to click it to close the dialog box. But the real problem is that when I :q exit the console, SBT freezes, and I need Ctrl-C to be able to type again. (And, yes, Ctrl-C shuts down SBT completely, not just the console.)

I think I might need to create a thread specifically for ScalaFX. For example, I have a way to stack one image on top of another, and I got an IllegalStateException when I tried to call this function, even if it actually doesn't display anything, it just creates a new Group with the previous two Node stacked accordingly. Unfortunately, I'm not sure how to create a new thread and make sure that all the images associated with this are related to this.

I already set fork := true in build.sbt , but this does not seem to affect the console.

== Update ==

I found initialCommands and cleanupCommands in the SBT documentation and tried to clear after everything when the console starts and ends. Values:

 initialCommands in console := """import org.dupontmanual.image._; org.dupontmanual.image.initialize()""" cleanupCommands in console := """org.dupontmanual.image.cleanUp()""" 

which are defined as follows:

 package object image { var masterFrame: JFrame = _ def initialize() { masterFrame = new JFrame() masterFrame.add(new JFXPanel()) masterFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) } def cleanUp() { println("exiting platform") Platform.exit() println("disposing of frames") Frame.getFrames().foreach { _.dispose() } println("frames all disposed") System.exit(0); } 

Here is the result of starting the console, and then trying to exit it:

 > console [info] Compiling 1 Scala source to /home/sysadmin/dm-workspace/dm-image/target/scala-2.10/classes... [info] Starting scala interpreter... [info] import org.dupontmanual.image._ Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51). Type in expressions to have them evaluated. Type :help for more information. scala> Hacker.display() scala> :q exiting platform disposing of frames frames all disposed Not interrupting system thread Thread[XToolkt-Shutdown-Thread,5,system] Not interrupting system thread Thread[AWT-XAWT,6,system] Not interrupting system thread Thread[Prism Font Disposer,10,system] Not interrupting system thread Thread[Java2D Disposer,10,system] Exception while removing reference: java.lang.InterruptedException java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) at com.sun.glass.utils.Disposer.run(Disposer.java:69) at java.lang.Thread.run(Thread.java:744) Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0" 

and he doesn't even leave the console. You still have to use Ctrl-C, which completely exits SBT.

Something is still working, but I can’t understand what it is. Hmm

+6
source share
1 answer

I think the problem is that you will need to fork the console somehow, so maybe this is the problem: https://github.com/sbt/sbt/issues/1918

The following idea seems to work: instead of the sbt console, you insert REPL like Ammonite. However, sbt run does not work, even with fork in run := true . But packing a thick can and a job that seems to work:

build.sbt

 name := "Foo" version := "0.1.0" scalaVersion := "2.11.7" libraryDependencies ++= Seq( "org.scala-lang.modules" %% "scala-swing" % "1.0.2", "com.lihaoyi" % "ammonite-repl" % "0.5.1" cross CrossVersion.full ) 

Project /build.properties

 sbt.version=0.13.9 

Project /plugins.sbt

 addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.1") 

Src / main / scala / foo / main.scala

 package foo import scala.swing._ object Main extends App { def test(): Unit = Swing.onEDT { new MainFrame { contents = new Label("App exits if you close window") } .open() } ammonite.repl.Main.run("") } 

Then

 $ sbt assembly ... $ java -jar target/scala-2.11/Foo-assembly-0.1.0.jar Loading... Welcome to the Ammonite Repl 0.5.1 (Scala 2.11.7 Java 1.8.0_66) @ foo.Main.test() 

The only oddity is that after the application exists, the shell character symbol is broken, it is possible that the problem is Ammonite, you can try the default Scala REPL.

0
source

All Articles