Search code examples
tornadofx

Transparent view


I would like to create a View (stage, window) with partially transparent background. I have an image containing alpha channel

an image containing alpha channel

I used this kind of scenes in JavaFx, where I had to set the scene fill to null and the root node background color to transparent. I tried the same with TornadoFX:

class NextRoundView : View("Következő kör") {

    override val root = vbox {
        style {
            backgroundColor = multi(Color.TRANSPARENT)
            backgroundImage = multi(URI.create("/common/rope-bg-500x300.png"))
            backgroundRepeat = multi(BackgroundRepeat.NO_REPEAT 
                                  to BackgroundRepeat.NO_REPEAT)
        }
        prefWidth = 500.0
        prefHeight = 300.0

        spacing = 20.0
        padding = insets(50, 20)
        text("A text") {
            font = Font.font(40.0)
            alignment = Pos.CENTER
        }

        button("OK")
        {
            font = Font.font(20.0)
            action {
                close()
            }
        }
        sceneProperty().addListener{ _,_,n ->
            n.fill = null
        }
    }

}

I'm calling the view like this:

NextRoundView().apply { 
    openModal(stageStyle = StageStyle.TRANSPARENT, block = true) 
}

However, the stage is still has background:

enter image description here

What have I missed?


Solution

  • You've made a couple of mistakes that causes this. First of all, you must never manually instantiate UICompoenents (View, Fragment). Doing so will make them miss important life cycle callbacks. One important callback is onDock, which is the perfect place to manipulate the assigned scene. Changing these two issues and also cleaning up some syntax leads to this code, which successfully makes the background transparent:

    class MyApp : App(MyView::class)
    
    class MyView : View() {
        override val root = stackpane {
            button("open").action {
                find<NextRoundView>().openModal(stageStyle = StageStyle.TRANSPARENT, block = true)
            }
        }
    }
    
    class NextRoundView : View("Következő kör") {
        override val root = vbox {
            style {
                backgroundColor += Color.TRANSPARENT
                backgroundImage += URI.create("/common/rope-bg-500x300.png")
                backgroundRepeat += BackgroundRepeat.NO_REPEAT to BackgroundRepeat.NO_REPEAT
            }
            prefWidth = 500.0
            prefHeight = 300.0
    
            spacing = 20.0
            padding = insets(50, 20)
            text("A text") {
                font = Font.font(40.0)
                alignment = Pos.CENTER
            }
    
            button("OK") {
                font = Font.font(20.0)
                action {
                    close()
                }
            }
        }
    
        override fun onDock() {
            currentStage?.scene?.fill = null
        }
    }
    

    Here is a screenshot of the app with the changes implemented:

    enter image description here