Comenzando en el desarrollo de aplicaciones de escritorio Scala+JavaFX
fxml (3)
Hay algunas cosas que debe saber al escribir aplicaciones JavaFX basadas en Scala.
Primero, aquí hay una muestra de la aplicación hola mundo:
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: _*)
}
}
Al ejecutarlo debes obtener:
Aquí hay un ejemplo oficial de hello world en Java: http://docs.oracle.com/javafx/2/get_started/hello_world.htm
Las principales diferencias son:
- Debe escribir el denominado objeto complementario con la
def main()
que inicia la aplicación real. -
Application.launch(classOf[Test], args: _*)
especificar que se ejecutará en el contexto de la clase Test y no del objeto complementario:Application.launch(classOf[Test], args: _*)
.
Si solo intenta ejecutar la aplicación directamente con Application.launch(args : _*)
obtendrá este error:
Excepción en el hilo "main" java.lang.RuntimeException: Error: la clase Test $ no es una subclase de javafx.application.Application
Para obtener más información sobre JavaFX, simplemente lea la documentación oficial: http://docs.oracle.com/javafx/index.html
¿Existe alguna guía o tutorial para crear una aplicación de escritorio Scala + JavaFX?
Estoy teniendo dificultades para encontrar una buena fuente y estoy utilizando IntelliJ IDEA como IDE.
Incluso las muestras de hello world de escritorio más simplistas me ayudarían mucho, porque tengo poca idea de por dónde empezar.
Actualización: Esto es lo que tengo ahora:
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)
}
}
Al ejecutarlo me sale:
Excepción en el hilo "main" java.lang.IllegalStateException: No en el hilo de la aplicación FX; currentThread = main
¿Cómo puedo hacer que muestre la ventana de hello world con la etiqueta?
Pude resolver este problema en scala_swing mucho más satisfactoriamente, ya que podría crear una instancia con parámetros y luego llamar a main para iniciar Swing más tarde.
Esta solución permite que los parámetros se obtengan en la aplicación FX a costa del uso de variables estáticas y otros posibles problemas. Una de ellas es que esto seguramente no es multihilo seguro.
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()
}
}
Se puede utilizar de esta manera.
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()
}
}