2

The main layout of my ScalaFX 8 application consists of a BorderPane. The top attribute contains a menu whereas bottom contains something similar to a status bar. My goal is to display a component for viewing 3D objects in the center of the BorderPane (acting as a SubScene).

stage = new PrimaryStage {
  scene = new Scene(900, 900, true, SceneAntialiasing.Balanced) {
    root = new BorderPane {
      top = createMenu // creates a menu inside of a VBox
      center = createViewer // should create a subscene inside of whatever is needed
      bottom = createStatusBar // creates a status bar inside of a VBox
    }
  }
}

I'm trying to create a minimal working example with a SubScene that only consists of black background and a simple sphere, no more, no less. The SubScene should use the whole space that is available in the center of BorderPane and resize accordingly. Unfortunately, I can't make it work.

Since the size of a SubScene is fixed, I assume it is necessary to embed the SubScene in another container (which is able to resize automatically) and bind the dimensions of the SubScene to the dimensions of the container around it.

def createViewer = {
  val bp = new BorderPane
  val subScene: SubScene = new SubScene(bp, 200, 200, true, SceneAntialiasing.Balanced) {
    fill = Color.Black
    width <== bp.width
    height <== bp.height
    content = new Sphere(3) { material = new PhongMaterial(Color.Red) }
    camera = new PerspectiveCamera(true) { ... }
  }
  bp.center = subScene
  subScene
}

The result looks like this:

enter image description here

Two obvious problems:

  • The SubScene keeps the fixed size from its constructor. In neither "maximizes" in the center of the outer BorderPane, nor does it do anything when the window gets resized
  • There is the red dot, but the bottom right corner of the SubScene is not black (?)

My assumption is that I have some problems understanding what the root element of the SubScene really is and what it does. I found another thread for JavaFX with a similar problem, this solution distinguishes between the root element of the SubScene (I'm not sure where that element comes from) and the Pane but I couldn't apply it to my case. Any help is appreciated. Thanks.

Community
  • 1
  • 1
fxfour
  • 143
  • 1
  • 10

1 Answers1

0

the idea here is to get the read only properties for the top level scene there is probably a more elegant way to do this, but this works

scene = new Scene(900, 900, true, SceneAntialiasing.Balanced) {
   // these are read only properties for the scene
   var tmpw = this. width
   var tmph =  this. height

   root = new BorderPane {

     top = new HBox {
       content = new Label {
         text = "menu"
       }
     }

     center = createView(tmpw,  tmph)

   }
 }
   width onChange show
   height onChange show

}

the idea here is to bind the read only properties to the properties of the subscene, then the subscene will re-size there is probably a way to avoid the 'this' key-word. I have tested this and the subscene re-sizes with the parent scene. I have omitted the PerspectiveCamera code block as you did not include what you were using

def createView(boundWidth : ReadOnlyDoubleProperty, boundHeight : ReadOnlyDoubleProperty):         BorderPane = {

  new BorderPane {

      center = new SubScene(boundWidth.get(), boundHeight.get(), true, SceneAntialiasing.Balanced) {
      fill = Color.BLACK
      content = new Sphere(3) { material = new PhongMaterial(Color.RED) }
      camera = new PerspectiveCamera(true)
       // bind the subscene properties to the parents 
        this.width.bind(boundWidth.add(-200))
        this.height.bind(boundHeight.add(-200))
    }

  }

}
Nigel Savage
  • 991
  • 13
  • 26
  • Thank you, that looks fine. Two last questions: 1. So there is no way to bind the size of the SubScene to the size of the BorderPane's center (you used the size of the scene instead, but it's okay for me)? 2. What are the last two lines from your first snippet good for (... onchange show)? Accidentally, I didn't copy paste them but your solution seems to work anyway – fxfour Dec 10 '14 at 17:06
  • fxfour,the original code you posted did not re size and that was the first issue to overcome, I am not happy using the this keyword, I think there should be a way to do this, with out the 'this'. this.width pulls in the ReadOnlyProperty of the node that it is the scope of, as you say I tried binding size of the BorderPane's center, it did not work. The 'width onChange show' allows the Scene to resize which then passes the new dimensions to the subscene through the binding. If I find a better way to get the ReadOnlyProperty maybe through a lazy eval I will update the answer. – Nigel Savage Dec 10 '14 at 18:34