当前位置: 首页 > 知识库问答 >
问题:

你怎么能让ScalaFX在SBT控制台上玩得很好?

夏宏旷
2023-03-14

我正在写一个图片素材库,供入门编程的学生玩。(我从DrRget的图片素材库中窃取了这个想法和模式。)

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

大部分是用Swing写的(那是< code>master分支),但是我在尝试把它转换成ScalaFX(见< code>scalafx分支),有一些问题。理想情况下,学生应该能够做如下事情:

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

并显示一个带有火车引擎的对话框。我尝试过在

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

独立对话框项目中,但是如果我在I dialog.showAndWait()之后包含System.exit(0),我会收到以下错误:

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"

(请注意,如果我尝试从控制台中的独立对话框运行应用程序,我会遇到同样的错误,因此我猜想在SBT控制台中调用系统退出(0)不是一个好主意。)

如果我离开系统。退出(0)line out,然后一切看起来都很好——大部分情况下。在我第一次显示对话框后,它不会使对话框聚焦,因此我必须单击它以取消对话框。但真正的问题是,当我:q退出控制台时,SBT挂起,我必须Ctrl-C,才能再次输入。(是的,Ctrl-C完全退出SBT,而不仅仅是控制台。)

我想我可能需要做的是创建一个专门用于ScalaFX的线程。例如,我有一种将一个图像叠加在另一个图像上的方法,当我试图调用该函数时,我得到了一个<code>非法状态异常,尽管它实际上没有显示任何内容,但只是创建了一个新的<code>组,其中前两个<code>节点被适当叠加。不幸的是,我不知道如何创建一个新线程,并确保与图像相关的所有内容都通过该线程运行。

我已经在build.sbt中设置了fork :=true,但这似乎与控制台没有区别。

==更新==

我在SBT留档中找到了初始命令清理命令,并尝试在控制台开始和结束时清理所有内容。这些值是:

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

cleanupCommands in console := """org.dupontmanual.image.cleanUp()"""

其定义如下:

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

以下是运行控制台然后试图退出的结果:

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

这甚至不会退出控制台。您仍然必须使用 Ctrl-C,它完全退出 SBT。

有东西还在运行,但我想不出来是什么。Grrr。

共有1个答案

傅峰
2023-03-14

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

下面的想法似乎是可行的:代替sbt控制台,你嵌入一个REPL,比如菊石。即使使用了< code>fork in run := true,仍然无法使用< code>sbt run。但是包装一个大罐子并运行它看起来确实有效:

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
)

项目/生成属性

sbt.version=0.13.9

项目/插件.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("")
}

然后

$ 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()

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

 类似资料:
  • 作为再现这个概念的一个非常基本的示例,我有这样一个类: 当我在这里嘲笑它的时候: 我再次得到IllegalStateException错误。 有人有想法吗?

  • 问题内容: 我正在尝试让JAXB与我的常规类一起使用,但是,它似乎不起作用,但是Java版本却可以。这是代码… 以下是方案: 如果2和3不加注释,则可以正常工作。 如果1和4不加注释,我得到: 如果1和5不加注释,我得到: 有任何想法吗? Java: Groovy: 测试: 问题答案: 取消注释1和4是使用Groovy设置JAXB的正确方法。它不起作用的原因是每个Groovy类都具有metaCla

  • 我使用scala sbt控制台测试我的方法。(命令:sbt然后控制台)但是在eclipse或其他外部编辑器中完成的代码更改不会在sbt控制台中得到反映。 每次,我都必须退出控制台(使用Crt D),然后使用console命令再次启动它以查看更改。 有人面临这个问题吗?有没有办法从控制台重新加载代码? 我使用的是64位Ubuntu,

  • 本文向大家介绍怎么才能让图文不可复制?相关面试题,主要包含被问及怎么才能让图文不可复制?时的应答技巧和注意事项,需要的朋友参考一下 -webkit-user-select: none; -ms-user-select: none; -moz-user-select: none; -khtml-user-select: none; user-select: none;

  • 我安装了IntelliJ的官方SBT插件(仍然在alpha中),我毫无问题地导入了一个Scala SBT项目(带有build.SBT)。但是当我尝试在Scala控制台中导入某些内容时,它会打印以下内容: 但当我在终端中运行SBT时启动完全相同的命令时,它工作得很好。 问题出在哪里?

  • 我想创建一个Android点击功能,使手机振动5秒。