[英]How do Iaunch a ScalaFX application from Scala?
I'm trying to launch the ScalaFX Hello World application from http://www.scalafx.org with the following code: 我正在尝试使用以下代码从http://www.scalafx.org启动ScalaFX Hello World应用程序:
package car.cadr
object ApplicationStarter {
def main(args: Array[String]) =
javafx.application.Application.launch(classOf[HelloStageDemo], args: _*)
}
To clarify, I have two Scala files in the car.cadr
package: ApplicationStarter.scala
and HelloStageDemo.scala
. 为了澄清,我在
car.cadr
包中有两个Scala文件: ApplicationStarter.scala
和HelloStageDemo.scala
。 HelloStageDemo.scala
starts and runs perfectly fine, but the compiler is complaining about not found: type HelloStageDemo
on ApplicationStarter.scala
. HelloStageDemo.scala
启动并运行完全正常,但编译器抱怨not found: type HelloStageDemo
在ApplicationStarter.scala
上not found: type HelloStageDemo
。 Even if I manually import it with import car.cadr.HelloStageDemo
the compiler still complains. 即使我用
import car.cadr.HelloStageDemo
手动导入它,编译器仍然会抱怨。
I'm using Scala 2.11.1 and ScalaFx 8.0.20-R6. 我正在使用Scala 2.11.1和ScalaFx 8.0.20-R6。
You have several problems here. 你有几个问题。
Let's start with the one the compiler is telling you about: not found: type HelloStageDemo
. 让我们从编译器告诉你的那个开始:
not found: type HelloStageDemo
。 This makes sense because the HelloStageDemo example defines an object
and not a class: so the scalac compiler actually outputs a class named HelloStageDemo$
(because you could also define a class HelloStageDemo
, and both need to be compiled with different names). 这是有道理的,因为HelloStageDemo示例定义了一个
object
而不是一个类:因此scalac编译器实际上输出了一个名为HelloStageDemo$
的类(因为您还可以定义一个class HelloStageDemo
,并且两者都需要使用不同的名称进行编译)。
Next, if you change your object HelloStageDemo
for a class HelloStageDemo
, you will get the following error: 接下来,如果为
class HelloStageDemo
更改object HelloStageDemo
class HelloStageDemo
,则会出现以下错误:
Error:(7, 36) overloaded method value launch with alternatives:
(x$1: String*)Unit <and>
(x$1: Class[_ <: javafx.application.Application],x$2: String*)Unit
cannot be applied to (Class[car.cadr.HelloStageDemo], String)
This is because the launch
method exists only with the following signatures (here in Java): 这是因为
launch
方法仅存在以下签名(此处为Java):
public static void launch(Class<? extends javafx.application.Application> appClass, String... args)
public static void launch(String... args)
But HelloStageDemo
is neither a String
nor a kind of javafx.application.Application
, so this cannot work. 但
HelloStageDemo
既不是String
也不是javafx.application.Application
,所以这不行。
This is because of the way ScalaFX's JFXApp
trait works. 这是因为ScalaFX的
JFXApp
特性的工作方式。 Here's the main metrhod that gets executed when you launch a ScalaFX application the usual way (ie., the main class is the one extending JFXApp
): 这是以常规方式启动ScalaFX应用程序时执行的主要方法(即,主类是扩展
JFXApp
):
import javafx.{application => jfxa}
trait JFXApp extends DelayedInit {
// ...code removed for clarity...
def main(args: Array[String]) {
JFXApp.ACTIVE_APP = this
arguments = args
// Put any further non-essential initialization here.
/* Launch the JFX application.
*/
jfxa.Application.launch(classOf[AppHelper], args: _*)
}
// ...code removed for clarity...
}
So, in ScalaFX, the class extending javafx.application.Application
isn't the one you implement, but a AppHelper
class provided by ScalaFX. 因此,在ScalaFX中,扩展
javafx.application.Application
的类不是您实现的类,而是AppHelper
提供的AppHelper
类。 Notice that the main method first sets the ACTIVE_APP
property on JFXApp
's companion object: in practice, what AppHelper
will do is start JFXApp.ACTIVE_APP
. 请注意,main方法首先在
JFXApp
的伴随对象上设置ACTIVE_APP
属性:实际上, AppHelper
将执行的操作是启动JFXApp.ACTIVE_APP
。 Here is the code: 这是代码:
package scalafx.application
private[application] class AppHelper extends javafx.application.Application {
def start(stage: javafx.stage.Stage) {
JFXApp.STAGE = stage
JFXApp.ACTIVE_APP.init()
if (JFXApp.AUTO_SHOW) {
JFXApp.STAGE.show()
}
}
override def stop() {
JFXApp.ACTIVE_APP.stopApp()
}
}
In conclusion, if you want to launch HelloStageDemo
but, for some reason, you don't want HelloStageDemo
to be the main class, the simplest solution would be to just call the main method - after all, it's just a method like any other: 总之,如果你想启动
HelloStageDemo
但是由于某种原因,你不希望HelloStageDemo
成为主类,最简单的解决方案就是调用main方法 - 毕竟,它只是一个像其他方法一样的方法:
package car.cadr
object ApplicationStarter {
def main(args: Array[String]) =
HelloStageDemo.main(Array())
}
But if, for some reason, you absolutely had to launch your ScalaFX application trough the javafx.application.Application.launch
method, I think the best solution would be to re-implement the AppHelper
class to your liking, which seems like it should be pretty simple. 但是,如果出于某种原因,您绝对必须通过
javafx.application.Application.launch
方法启动ScalaFX应用程序,我认为最好的解决方案是根据自己的喜好重新实现AppHelper
类,这似乎应该是很简单。
Here is a simple template for launching ScalaFX applications. 这是一个用于启动ScalaFX应用程序的简单模板。
object MyApp {
def main(args: Array[String]) {
MyApp.launch(classOf[MyApp], args: _*)
}
}
class MyApp extends JFXApp {
override def start(primaryStage: Stage): Unit = {
// initialization here
}
}
Non ScalaFX solution: 非ScalaFX解决方案:
I know this question is answered and old. 我知道这个问题已经回答了。 But if you want to use javafx.application.Application, to launch.
但是如果你想使用javafx.application.Application来启动。 Just set different names for the class and the object, with the result that there is no "MyClass$.class" and "MyClass.class" where the second one isn't the Applications Child but the object.
只需为类和对象设置不同的名称,结果是没有“MyClass $ .class”和“MyClass.class”,其中第二个不是Applications Child而是对象。
Solved my problem in a neat way. 以一种巧妙的方式解决了我的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.