2

I am quite new to Scala and ScalaFX, so I probably do not understand this correctly. My issue: I add a node (f.e. Button) to a ScalaFX Pane (f.e. VBox). When I access the children of the Pane the children type changed from ScalaFX Button to JavaFX Button.

When I have a look at the source code of ScalaFX I can see that everything is done with delegates. So is the ScalaFX node lost? I think there is done some magic (for me as a newbie) with implicit conversion from ScalaFX to JavaFX. Is it possible to do an implicit conversion the other way round? Do I use ScalaFX correctly?

I wanted to go through all children of a Pane. When a child is from special type I wanted to perform some operations with this child. Now I would have to check for JavaFX type and work on a JavaFX node, which does not appears like clean code to me.

Any commments welcome. Thanks in advance.

I attached a running example.

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.scene.Scene
import scalafx.scene.control.Button
import scalafx.scene.layout.VBox
import scalafx.stage.WindowEvent

object TestChildren extends JFXApp {
  stage = new PrimaryStage {
    val contentPane = new VBox()
    val b1 = new Button("B1")
    contentPane.children.add(b1)
    scene = new Scene (contentPane)

    println(b1.getClass)
    println("--")
    for (child <- contentPane.children) {
      println(child.getClass)
    }
  }
}
hami
  • 443
  • 5
  • 13

1 Answers1

1

Yes, there is an implicit conversion. I do not know which IDE you are using, but for example IntelliJ 14.1 with the Scala plugin indicates implicit conversions, which is a really useful feature.

In your case,

contentPane.children.add(b1)

is the line where the implicit conversion happens. The explicit form is

contentPane.children.add(Button.sfxButton2jfx(b1))

where the implicit conversion is a one-liner in scalafx.scene.control.Button:

implicit def sfxButton2jfx(v: Button): jfxsc.Button = if (v != null) v.delegate else null
Kulu Limpa
  • 3,501
  • 1
  • 21
  • 31
  • I use and IntelliJ and now could see the implicit conversion. Thanks. How would you check, if the children are of a special type/class? I iterate the children and check for the JavaFX classes and create then a ScalaFX object out of the JavaFX object. Is this ok? It does not look like clean code for me. Mixing JavaFX and ScalaFX. Could it be usefull to define an implcit conversion from JavaFX to ScalaFX or would this produce any undesired sideeffects? – hami May 27 '15 at 15:17
  • @hami Admittedly I do know neither ScalaFX nor JavaFX but it looks like ScalaFX is just providing a more Scala-idiomatic syntax for JavaFX. I'm guessing they're mostly interchangeable and you could convert both of them into the other. I do not see any clean-code violation in that, though, as you have realized, implicits conversions can be confusing without proper tools. Regarding your type-checking: Scala has a really strong static type system; often you do not need to check the dynamic type. In this case, `contentPane.children` is of type `ObservableList[javafx.scene.Node]` ... – Kulu Limpa May 27 '15 at 23:10
  • ... so there is no need to check the dynamic type. If you do need to know the runtime type, generally, I think the cleanest way is to use a partial function, e.g., `match`-clause. Finally, there aren't any special dangers in having an implicit conversion from `A` to `B` and one from `B` to `A`: At most one implicit conversion is applied and implicit conversions only happen at compile time. – Kulu Limpa May 27 '15 at 23:10