ScalaFX instance / node (and attribute) reference at different levels of hierarchy

11 views
Skip to first unread message

Bene Volent

unread,
Oct 8, 2019, 3:41:35 PM10/8/19
to ScalaFX Users
I scribbled this also on stackoverflow, but here it is also to more targeted audience:

Given that I have a node hierarchy as follows (numbers are the levels of the branch)
 1          2          3              4
VBox -+-> VBox ---> StackPane -+-> ImageView
      +-> Label                +-> Rectangle

I can access the Rectangle attributes directly, but it is easy to make mistakes as the list references children.get(0) are directly dependent from order of the children as the nodes are positioned in parent. 

val lvone = vbnode.children  // VBox (main)
val lvtwo = lvone.get(0)  // VBox
val lvthree = lvtwo.asInstanceOf[javafx.scene.layout.VBox].children.get(0)  // StackPane
val lvfour = lvthree.asInstanceOf[javafx.scene.layout.StackPane].children.get(0)  // Rectangle
if (lvfour.isInstanceOf[javafx.scene.shape.Rectangle]) lvfour.asInstanceOf[javafx.scene.shape.Rectangle].style = "-fx-fill: #a001fc;"

If I want to make safer references disregarding the order at each level of node hierarchy I can loop through the level until I come across the node type of interest. here's a mock-up of such beast:

val levelone = vbnode.children   
println("LV1 Node userData:"+vbnode.userData)  // my database reference for the main / container element
println("LV1 Parent children class:"+levelone.get(0).getClass) // class javafx.scene.layout.VBox
for (leveltwo <- levelone) {
  println("LV2 Children Class:"+leveltwo.getClass)
  println("LV2 Children Class Simple Name:"+leveltwo.getClass.getSimpleName)  // VBox
  if (leveltwo.getClass.getSimpleName == "VBox") {
    leveltwo.style = "-fx-border-width: 4px;" +
                     "-fx-border-color: blue yellow blue yellow;"
    for (levelthree <- leveltwo.asInstanceOf[javafx.scene.layout.VBox].children) {
      println("LV3 children:"+levelthree.getClass.getName)
      if (levelthree.getClass.getSimpleName == "StackPane") {
        for (levelfour <- levelthree.asInstanceOf[javafx.scene.layout.StackPane].children) {
          println("LV4 children:"+levelfour.getClass.getName)
          if (levelfour.getClass.getSimpleName == "Rectangle") {
            if (levelfour.isInstanceOf[javafx.scene.shape.Rectangle]) println("Rectangle instance confirmed")
            println("LV4 Found a Rectangle")
            println("original -fx-fill / CSS:"+ levelfour.asInstanceOf[javafx.scene.shape.Rectangle].style)
            levelfour.asInstanceOf[javafx.scene.shape.Rectangle].style = "-fx-fill: #a001fc;"
          } // end if
        } // end for levelfour
      } // end if
    } // end for levelthree
  } // end if
} // end for leveltwo


Questions: Is there smarter way to reach the nodes at different levels? and is there smarter way to do the type casting of node types, since only javafx API based references are acceptable? Options I am using are:
1- simple / shortcut way referring to level 2 -VBox Node in this case: evaluation by using leveltwo.getClass.getSimpleName == "VBox" , which is the shortcut from API jungle. But is it efficient and safe?
2- cluttering way by using probably the "by the book style": if (levelfour.isInstanceOf[javafx.scene.shape.Rectangle])

Now in reference to the fully qualified reference based on javafx ie. javafx.scene.shape.Rectangle, I would like to use scala reference instead (after all I have them imported), but I get an error, which enforces me to make the easy workaround and adopt the javafx based reference. Not a big deal as I can use javafx reference, but I wander if there is scalafx based option?





Reply all
Reply to author
Forward
0 new messages