Since TornadoFX manages all Views and Fragments, I wonder if there is an easy way to set a graphic icon for all of them. I don't think there is a direct way to do this with JavaFX.
myStage.icons += Image("icon.png")
Sorry for beeing dense, but I'm not sure I understand what you mean, can you elaborate?
Unless I missed an already built-in feature with JavaFX, if you want to apply an icon to _every_ window, stage, dialog, etc. you have to do it manually to each one. Is it possible to set the icon in one place and it is used for every View and Fragment-backed dialog?
Ah! That would be easy for Fragments using the openModal() function, but not for Views. I'll think about this and find a solution, shouldn't be too hard :)
If we add a function that creates a new stage, this function could automatically copy the icons from the primary stage. So whenever you instantiate a stage via this option, your icons would be in sync. Would that be satisfactory?
That would be awesome!
OK, we'll go for that. I moved Fragment.openModal to UIComponent to it supports View as well, and added the icon trick to that one. I think the name might be a misnomer now, but could you check if this works for you, or tell me what we would need to change? We could rename this, fix it and make a backwards compatible version of openModal and possibly deprecate that to move forward.
I'll follow up on this when I get a chance today...
Haven't forgotten this. I will follow up when I resume writing the guide tomorrow. I'm kind of testing as I document stuff : )
No worries :) I'll start preparing for a release and document the features from the changelog as well :)
@thomasnield did you get around to testing if this works as intended for you? :)
I just got to my computer to hammer through my queue of things : ) Give me ~30 minutes
Perfect :) Working on closing a few issues, looking at Alert builders now :)
Working on it now...
Sorry if I'm being slow today, what exactly would I configure to set up a universal icon with this modification?
Haha, no problem :) Either configure the stage.icons in your App start() function, or any other place later on via FX.primaryStage.icons.
The stage should get the icons, and any new stage created with the openModal() function should get this icon. I can create a demo app if needed :)
Yeah I just figured that out with the FX.primaryStage.icons. Trying to run it now.
Random problem. Keep getting this error when trying to run this application.
Exception in Application constructor
Exception in thread "main" java.lang.NoSuchMethodException: MyAppTest.main([Ljava.lang.String;)
at java.lang.Class.getMethod(Class.java:1786)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:125)
class MyAppTest: SingleViewApp() {
override val root = VBox()
init {
FX.primaryStage.icons += Image("C:\\git\\tornadofx\\src\\test\\kotlin\\logo.png")
with(root) {
button("Press Me") {
setOnAction { MyDialog().openModal() }
}
}
}
class MyDialog: Fragment() {
override val root = VBox()
init {
with(root) {
label("Dialog")
}
}
}
}
FX.primaryStage is not initialized yet in the init method, so you would have to do this in start():
override fun start(stage: Stage) {
stage.icons += Image("file:///path/to/icon")
super.start(stage)
}
Also remember to supply a valid URL to the Image constructor (starting with proto://). Does that help?
Yep! Got it. Very nice. I approve.
class MyAppTest: SingleViewApp() {
override val root = VBox()
init {
with(root) {
button("Press Me") {
setOnAction { MyDialog().openModal() }
}
}
}
override fun start(stage: Stage) {
super.start(stage)
FX.primaryStage.icons += Image("logo.png")
}
class MyDialog: Fragment() {
override val root = VBox()
init {
with(root) {
label("Dialog")
}
}
}
}

Cool! You can apply the icon to stage, no need to apply it to primaryStage.
I could however add a function that will add this as a "global" icon, and even make sure that the primaryStage is available when it's added. Let me try, hang on.
That might be more intuitive : )
Can you attach logo.png so I have something to test with? hehe :)
Hmm. That was a bit more involved than I though. Hang on.
Allright, try the shiny new addStageIcon function :) Needed to add boolean property that keeps track of "app initialized state". This can be run from the init function.
Sorry here is the logo. For some reason addStageIcon isn't applying the icon...

Thanks :) Hmm.. yeah, I can't set a breakpoint in that method. I'll report back when I have it sorted!
Oh, wow :) That's the first time Kotlin has bitten me...
I declared the function as fun addStageIcon(icon: Image) = { code here } instead of fun addStageIcon(icon: Image) { code here }. In other words, the function created a function instead of executing the code. Commited a fix now :)
AH! Tricky... that explains everything.
Most helpful comment
Allright, try the shiny new
addStageIconfunction :) Needed to add boolean property that keeps track of "app initialized state". This can be run from theinitfunction.