如何让ScalaFX在SBT控制台中发挥​​出色?

TOB*_*TOB 7 scala javafx sbt scalafx

我正在为介绍性编程学生编写一个图像库.(我从DrRacket的图像库中偷走了这个想法和模式.)

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

它主要用Swing编写(这是master分支),但我试图将其转换为ScalaFX(参见scalafx分支),并且存在一些问题.理想情况下,学生应该能够做以下事情:

scala> import org.dupontmanual.image._
scala> TrainEngine.display()
Run Code Online (Sandbox Code Playgroud)

并有一个显示火车引擎的对话框.我已经尝试过使用代码了

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

stand-alone-dialog项目中,但如果我System.exit(0)在我之后包含dialog.showAndWait(),我会收到此错误:

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"
Run Code Online (Sandbox Code Playgroud)

(请注意,如果我尝试在控制台中运行Appfrom ,我会得到相同的错误stand-alone-dialog,因此我猜测System.exit(0)在SBT控制台中调用不是一个好主意.)

如果我离开这System.exit(0)条线路,那么事情似乎也很好 - 大多数情况下.在我第一次显示对话框后,它不会使对话框成为焦点,因此我必须单击它才能关闭对话框.但真正的问题是,当我:q退出控制台时,SBT挂起,我必须Ctrl-C能够再次打字.(并且,是的,Ctrl-C完全退出SBT,而不仅仅是控制台.)

我想我可能需要做的是专门为ScalaFX创建一个线程.例如,我有一种方法可以将一个图像堆叠在另一个图像的顶部,IllegalStateException当我尝试调用该函数时,我得到了一个,即使它实际上没有显示任何内容,只需创建一个新的Group,前两个Node适当地堆叠.不幸的是,我不确定如何创建一个新线程,并确保所有与图像相关的内容贯穿始终.

我已经开始fork := truebuild.sbt,但这似乎与控制台没什么区别.

==更新==

我发现initialCommandscleanupCommands在SBT文档中尝试在控制台启动和结束后清理所有内容.价值观是:

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

cleanupCommands in console := """org.dupontmanual.image.cleanUp()"""
Run Code Online (Sandbox Code Playgroud)

由此定义:

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);
  }
Run Code Online (Sandbox Code Playgroud)

这是运行控制台然后尝试退出的结果:

> 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"
Run Code Online (Sandbox Code Playgroud)

而且甚至没有退出控制台.您仍然必须使用Ctrl-C,它完全退出SBT.

有些东西还在运行,但我无法弄清楚它是什么.哎呀.

0__*_*0__ 0

我认为问题是你需要以某种方式分叉控制台,所以也许是这个问题: https: //github.com/sbt/sbt/issues/1918

以下想法似乎可行:您嵌入 REPL,例如 Ammonite,而不是 sbt 控制台。即使使用,仍然sbt run不起作用fork in run := true。但是打包一个胖罐子并运行似乎确实有效:

构建.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
)
Run Code Online (Sandbox Code Playgroud)

项目/build.properties

sbt.version=0.13.9
Run Code Online (Sandbox Code Playgroud)

项目/plugins.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.1")
Run Code Online (Sandbox Code Playgroud)

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("")
}
Run Code Online (Sandbox Code Playgroud)

然后

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
)
Run Code Online (Sandbox Code Playgroud)

唯一奇怪的是,应用程序存在后,shell 字符回显被破坏,这可能是 Ammonite 的问题,您可能想尝试使用默认的 Scala REPL。