Question

package pGrid
package pUIFx
import pUtil._    

object DevAppFx extends AppFx
{
  println("Begining DevFxApp object constructor in package pGrid.pUIFx")   
  //devStart 
}

package pGrid
package pUIFx
import pGeom._
import pGrid.pDev._

import scalafx.application._
import scalafx.application.JFXApp._
import scalafx.scene._
import scalafx.scene.paint._

class AppFx extends JFXApp with DevTr
{   
  println("Creating stage")
  stage =  new PrimaryStage
  {
    x = 3850
    y = 200
    width = 1000
    height = 800          
    scene = new Scene
  }
  def openEFO(de: DescEFlatOne): Unit =
  {
    println("def in AppFx")
    stage.scene = ScrEditFx(stage, de)            
  }
}

The DevAppFx object constructor runs, including the println ("Beginning ...

The class AppFx constructor does not run including the println ("creating stage"). The openEFO method can be called but the stage variable is null.

Edit this is a simplification. There will be a lot more functionality in DEVAppFx and AppFx, so its important to be able to keep the functionality separate.

Was it helpful?

Solution

I think the issue here is that scalafx.application.JXFApp is a class that extends the scala.DelayedInit trait. As such, some Scala magic happens under the hood: see the scala.DelayedInit docs for more. Unfortunately, DelayedInit is buggy and plays havoc with sub-class initialization/construction code - such as your AppFx class not executing its constructor.

There's no easy solution to this, I'm afraid. Until the DelayedInit behavior is resolved, or until we find a better way to initialize ScalaFX, your best bet is to merge DevAppFx and AppFx into a single object, which should work as expected.

For example:

package pGrid
package pUIFx
import pGeom._
import pGrid.pDev._

import scalafx.application._
import scalafx.application.JFXApp._
import scalafx.scene._
import scalafx.scene.paint._

object AppFx extends JFXApp with DevTr
{   
  println("Creating stage")
  stage =  new PrimaryStage
  {
    x = 3850
    y = 200
    width = 1000
    height = 800          
    scene = new Scene
  }
  // Relocate DevAppFx init here...
  println("Begining DevFxApp object constructor in package pGrid.pUIFx")   
  //devStart 
  def openEFO(de: DescEFlatOne): Unit =
  {
    println("def in AppFx")
    stage.scene = ScrEditFx(stage, de)            
  }
}

UPDATE:

I did some more digging around, and scalafx.application.JFXApp didn't do a great job of implementing the semantics of the scala.DelayedInit trait. In essence, it was only storing the construction/initialization code of the class/object at the bottom of the inheritance hierarchy, and dropping everything else. For further details, there is a ScalaFX bug report for this issue.

So, in your example, the construction code for the object DevAppFx was replacing the construction code for your class AppFx, instead of storing both, resulting in the symptoms you observed.

I've committed a patch to the default and SFX-8 branches of ScalaFX on Google Code, which you're free to utilize. Alternatively, if you're prepared to wait a few weeks, the next updates published to the Sonatype OSS to have the patch will be 1.0.0-R9 (for the JavaFX 2 equivalent) and 8.0.0-R5 (for the JavaFX 8 equivalent).

This patch should allow your original code to run unmodified. If you get a chance to try it out, let me know how you get on...

OTHER TIPS

I've use the information about possible bugs in DelayedInit from Mike Allen's answer. However I want to keep the functionality separate rather than combining it into one object. Reading the docs, the problem is with classes and Objects not with traits that inherit from JFXApp and DelayedInit, so I have converted AppFx into a trait and moved the Stage creation into a method

object DevAppFx extends AppFx with DevTr
{
  openStage
  devStart 
}

____________--

trait AppFx extends JFXApp with StratApp
{
  def openStage: Unit = stage =  new PrimaryStage
  {
    x = 3850
    y = 200
    width = 1000
    height = 800          
    scene = new Scene
  }
  override def openEFO(de: DescEFlatOne): Unit = stage.scene = ScrEditFx(this, de)   
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top