Scala + JavaFX 桌面应用程序开发入门
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12124657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting started on Scala + JavaFX desktop application development
提问by Tower
Is there some guide or walkthrough to building a Scala + JavaFX desktop application?
是否有构建 Scala + JavaFX 桌面应用程序的指南或演练?
I'm having hard time finding a good source and I am using IntelliJ IDEA as the IDE.
我很难找到一个好的来源,我使用 IntelliJ IDEA 作为 IDE。
Even the most simplistic desktop hello world samples would help a lot, because I have little clue where to start.
即使是最简单的桌面 hello world 示例也会有很大帮助,因为我几乎不知道从哪里开始。
Update:This is what I have now:
更新:这就是我现在所拥有的:
import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.StackPane
import javafx.stage.Stage
import javafx.scene.control.Label
class Test extends Application {
override def start(primaryStage: Stage) {
primaryStage.setTitle("Sup!")
val root = new StackPane
root.getChildren.add(new Label("Hello world!"))
primaryStage.setScene(new Scene(root, 300, 300))
primaryStage.show()
}
}
object Test {
def main(args: Array[String]) {
val t = new Test
t.start(new Stage)
}
}
Running it I get:
运行它我得到:
Exception in thread "main" java.lang.IllegalStateException: Not on FX application thread; currentThread = main
线程“main”中的异常 java.lang.IllegalStateException:不在 FX 应用程序线程上;当前线程 = 主要
How can I get it to display the hello world window with the label?
我怎样才能让它显示带有标签的 hello world 窗口?
回答by Kai Sellgren
There are a few things to know when writing Scala based JavaFX applications.
编写基于 Scala 的 JavaFX 应用程序时需要了解一些事项。
First, here's a sample hello world app:
首先,这是一个示例 hello world 应用程序:
import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.StackPane
import javafx.stage.Stage
import javafx.scene.control.Label
class Test extends Application {
println("Test()")
override def start(primaryStage: Stage) {
primaryStage.setTitle("Sup!")
val root = new StackPane
root.getChildren.add(new Label("Hello world!"))
primaryStage.setScene(new Scene(root, 300, 300))
primaryStage.show()
}
}
object Test {
def main(args: Array[String]) {
Application.launch(classOf[Test], args: _*)
}
}
Running it you should get:
运行它你应该得到:


Here's an official hello world example in Java: http://docs.oracle.com/javafx/2/get_started/hello_world.htm
这是 Java 中的官方 hello world 示例:http: //docs.oracle.com/javafx/2/get_started/hello_world.htm
The main differences are:
主要区别是:
- You have to write the so-called companion object with the
def main()that launches the actual application. - You have to specify that it will be run in context of the class Test, and not the companion object:
Application.launch(classOf[Test], args: _*).
- 您必须使用
def main()启动实际应用程序的编写所谓的伴生对象。 - 您必须指定它将在类 Test 的上下文中运行,而不是伴随对象:
Application.launch(classOf[Test], args: _*)。
If you just try to run the application directly with Application.launch(args : _*)you will get this error:
如果您只是尝试直接运行该应用程序,Application.launch(args : _*)则会收到此错误:
Exception in thread "main" java.lang.RuntimeException: Error: class Test$ is not a subclass of javafx.application.Application
线程“main”中的异常 java.lang.RuntimeException:错误:类 Test$ 不是 javafx.application.Application 的子类
To learn more about JavaFX, just read the official documentation: http://docs.oracle.com/javafx/index.html
要了解有关 JavaFX 的更多信息,只需阅读官方文档:http: //docs.oracle.com/javafx/index.html
回答by MHJ
You can use this way.
您可以使用这种方式。
class BuildFx extends Application{
override def start(primaryStage: Stage): Unit = {
primaryStage.setTitle("Scala")
var btn=new Button("Say Hello Scala")
val root=new StackPane()
root.getChildren().add(btn)
primaryStage.setScene(new Scene(root, 300, 300))
primaryStage.show()
}
def launchIt():Unit={
Application.launch()
}
}
///////////////////////////////////////////////////////////
object Init{
def main(args: Array[String]): Unit = {
val buildFx=new BuildFx
buildFx.launchIt()
}
}
回答by Bday
I was able to solve this problem in scala_swing much more satisfactorily because you could instantiate an instance with parameters then call main on it to start Swing later.
我能够更令人满意地在 scala_swing 中解决这个问题,因为您可以使用参数实例化一个实例,然后在其上调用 main 以稍后启动 Swing。
This solution allows parameters to be obtained in the FX application at the cost of using static var and possible other issues. One being that this is surely not multi-thread safe.
此解决方案允许在 FX 应用程序中以使用静态变量和可能的其他问题为代价获取参数。一是这肯定不是多线程安全的。
package hack
/**
* Created by WorkDay on 8/11/16.<br>
* <br>
* HelloTest shows a method which allows parameters to be passed
* into your javaFX application as it is started
* this allows it to be connected to non-FX code that existed before it.
*
* You could also pass a reference to the Application back
* into the non-FX code if needed.
*/
import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.StackPane
import javafx.stage.Stage
import javafx.scene.control.Label
case class Data(data: String)
object SomeOtherCode extends App {
HelloTest.launch(Data("brave"), Data("new"))
}
object HelloTest {
var data1: Data = _
var data2: Data = _
def launch(data1: Data, data2: Data) = {
HelloTest.data1 = data1
HelloTest.data2 = data2
Application.launch(classOf[HelloTest])
}
}
private class HelloTest extends Application {
val data1: Data = HelloTest.data1
val data2: Data = HelloTest.data2
override def start(primaryStage: Stage) {
primaryStage.setTitle("Sup!")
val root = new StackPane
root.getChildren.add(new Label(s"Hello ${data1.data} ${data2.data} world!"))
primaryStage.setScene(new Scene(root, 300, 300))
primaryStage.setX(0)
primaryStage.setY(0)
primaryStage.show()
}
}

