Начало работы в Scala + разработке приложений для JavaFX
Есть ли какое-нибудь руководство или пошаговое руководство для создания рабочего стола Scala + JavaFX?
Мне сложно найти хороший источник, и я использую IntelliJ IDEA в качестве среды IDE.
Даже самые упрощенные образцы рабочего стола 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 {
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)
}
}
Запустив его, я получаю:
Исключение в потоке "main" java.lang.IllegalStateException: не на FX прикладная нить; currentThread = main
Как я могу заставить его отображать окно hello world с меткой?
Ответы
Ответ 1
Есть несколько вещей, которые нужно знать при написании приложений JavaFX на основе Scala.
Во-первых, здесь пример приложения 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: _*)
}
}
Запустив его, вы должны получить:
![enter image description here]()
Вот официальный пример приветствия в Java: http://docs.oracle.com/javafx/2/get_started/hello_world.htm
Основные отличия:
- Вы должны написать так называемый объект-компаньон с
def main()
, который запускает фактическое приложение.
- Вы должны указать, что он будет запущен в контексте класса Test, а не сопутствующего объекта:
Application.launch(classOf[Test], args: _*)
.
Если вы просто попытаетесь запустить приложение напрямую с помощью Application.launch(args : _*)
, вы получите эту ошибку:
Исключение в потоке "main" java.lang.RuntimeException: Ошибка: class Тест $не является подклассом javafx.application.Application
Чтобы узнать больше о JavaFX, просто прочитайте официальную документацию: http://docs.oracle.com/javafx/index.html
Ответ 2
Я смог решить эту проблему в scala_swing гораздо более удовлетворительно, потому что вы могли бы создать экземпляр с параметрами, а затем вызвать main на нем, чтобы начать Swing позже.
Это решение позволяет получить параметры в приложении 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()
}
}
Ответ 3
Вы можете использовать этот способ.
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()
}
}