Re: Is it possible to cast a javafx.scene.Node back to an instance of a child of a scalafx class?

935 views
Skip to first unread message

Alain FAGOT BÉAREZ

unread,
Dec 17, 2012, 12:07:28 PM12/17/12
to scalaf...@googlegroups.com
Frank,

In this case, you would have to wrap your JavaFX instance back into its corresponding ScalaFX wrapper class, thus creating a new instance of the wrapper while maintaining the very same instance of the underlying JavaFX delegate.

val scalafxCircle = MyCircle(myContent.children.get(0))

Regards,
Alain

Em domingo, 16 de dezembro de 2012 15h12min01s UTC-3, Frank Fischer escreveu:
This code compiles and runs:

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.layout.HBox
import scalafx.stage.Stage

import javafx.scene.shape.Circle  // ClassCastException with scalafx.scene.shape.Circle


class MyCircle extends Circle { def myMethod="It works!" }

object Example extends JFXApp {
  val myCircle  = new MyCircle;  myCircle.setRadius(20)
  val myContent = new HBox  { content=myCircle }
  val myScene   = new Scene { content=myContent }
  val myStage   = new Stage { scene=myScene; width=100; height=100 }
  stage         = myStage
  
  val javafxCircle = myContent.children.get(0).asInstanceOf[MyCircle]
  println(javafxCircle.myMethod)
}

When i use a scalafx.scene.shape.Circle the code compiles but a 
ClassCastException is thrown at runtime.
Are children of scalafx classes unretrievable when they are available
only as a javafx.scene.Node ?

Frank

Alain FAGOT BÉAREZ

unread,
Dec 17, 2012, 5:31:49 PM12/17/12
to scalaf...@googlegroups.com
Frank,

Had I understood your need correctly, I would have directed you to my own experiments with extending a custom layout:

Just as you did, I ended extending from the JavaFX original class. In my case, all I needed was ability to override some layout methods, i.e. layoutChildren.
I would not advertise my code as the cleanest ever for that purpose. But it is the better I achieved as translation from my original JavaFX Script 1.3 version.

I will try considering your trick of referencing the ScalaFX wrapper from within the JavaFX extending class. It might simplify some of my code down there...

Bis bald,
Alain

PS: You might want to consider the import of scalafx.scene.input.MouseEvent instead of its JavaFX counterpart since you are using it from within a closure wrapper.

Em segunda-feira, 17 de dezembro de 2012 17h26min10s UTC-3, Frank Fischer escreveu:
Thanks for the reply, Alain.

My example was somewhat misleading but your answer 
led me to a solution.
Below is an updated example that runs fine.

I want to write widgets (like the simplified MyCircle) 
that have complex functionality (like onMouseClicked)
and own data (like colorWhenClicked).

If i add a scalafx Circle (wrapper) as a child to some Parent there
seems to be no way to access MyCircle data or methods from the
javafx child Nodes that the Parent provides (allthough MyCircle runs 
correct when written in that way).

But i want to access my widgets by traversing the scene graph.

If i extend my widgets from JavaFX classes and wrap them to
scalafx in the constructor (sfxThis) the widgets can be written
with the advantages of scalafx and are reachable by the scene 
graph.

Not perfect but the code is better to read than with JavaFX alone.

Frank

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.layout.HBox
import scalafx.stage.Stage
import scalafx.scene.paint.Color
import javafx.scene.input.MouseEvent


class MyCircle extends javafx.scene.shape.Circle {
  val sfxThis = new scalafx.scene.shape.Circle(this)
  val colorWhenClicked=Color.RED
  sfxThis.onMouseClicked = { (e: MouseEvent) => sfxThis.fill=colorWhenClicked }
  def myMethod="colorWhenClicked: " + colorWhenClicked.toString
}

object Example2 extends JFXApp {
  val myCircle  = new MyCircle;  myCircle.setRadius(20)
  val myContent = new HBox  { content=myCircle }
  val myScene   = new Scene { content=myContent }
  val myStage   = new Stage { scene=myScene; width=100; height=100 }
  stage         = myStage
  
  val circleObtainedFromSceneGraph = myContent.children.get(0).asInstanceOf[MyCircle]
  println(circleObtainedFromSceneGraph.myMethod)

QuidNovi

unread,
Aug 15, 2013, 12:45:22 PM8/15/13
to scalaf...@googlegroups.com
I was about to ask how to do some custom layout / override layoutChildren  on this list.

Thanx to your answers I ended up with this solution (I think I took the opposite approach, in fact) :

  val view = new sfxParent { // <= some scalafx Parent class or your own custom subclass

    override val delegate = new jfxParent { // <= override the JavaFx delegate wrapped inside the ScalaFx type

      override def layoutChildren() { // <= override what you want inside it
        super.layoutChildren()
        // Custom layouting code
      }

    }
  }

I think it's a bit cleaner to override the JavaFx delegate inside the ScalaFx wrapper than doing the other way around (referencing a wrapper inside your custom JavaFx type).
Reply all
Reply to author
Forward
0 new messages