edvin / tornadofx

Lightweight JavaFX Framework for Kotlin
Apache License 2.0
3.67k stars 269 forks source link

Trying to get cellFormat graphic in listview working #1187

Open SKeeneCode opened 4 years ago

SKeeneCode commented 4 years ago

I have a view model tag that has two String properties and I am trying to use cellFormat to customize how they appear in a listview:

                listview(wikiViewModel.tagList) {
                    cellFormat {
                        graphic = hbox {
                            label(it.name)
                            label(" and ${it.colour}")
                        }
                    }
                }

When adding a element to the tagList I get the following error:

java.lang.reflect.InaccessibleObjectException: Unable to make protected javafx.collections.ObservableList javafx.scene.Parent.getChildren() accessible: module javafx.graphics does not "opens javafx.scene" to unnamed module @766031bc

This is with TornadoFX 2.0 snapshot and javafx 13. Am I not using the cellFormat correctly? My project is not modular so I don't understand why it wants javafx opened anywhere?

Note: I can get just text to work:

                listview(wikiViewModel.tagList) {
                    cellFormat {
                        text = it.name.value
                    }
               }

but anything to do with graphic seems to fail for me.

SchweinchenFuntik commented 4 years ago

hbox is likely to be added to listview. this may be the cause of the error. Try HBox().apply {}

SchweinchenFuntik commented 4 years ago

PS: you need to check which receiver (this) the hbox function captures

SKeeneCode commented 4 years ago

Thanks @SchweinchenFuntik that fixed it you've saved me a big headache here!

Can you help me understand what exactly was wrong. What do you mean by hbox is likely to be added to listview?

SchweinchenFuntik commented 4 years ago

hbox is a higher-order function (a function that takes a different function, apply is also a higher-order function) with a receiver - they are also called builders, since they change scopes. All tornadofx functions are built on such functions, they are called on EventTarget.

https://github.com/edvin/tornadofx/blob/master/src/main/java/tornadofx/Layouts.kt#L137

SchweinchenFuntik commented 4 years ago

in the code below most likely the receiver was listview itself and not its cell

deggers commented 4 years ago

Mhm. I cannot reproduce this. Neither do I understand your argument of using HBox().apply rather :(

class ListViewTest : View() {
    private val numbers = (1..10).map { it.toString() }.asObservable()
    override val root: Parent = listview(numbers) {
        cellFormat {
            graphic = hbox {
                label(it)
                label(" and $it")
            }
        }
    }
}

Works for me perfectly fine with Java13 and openfx13 and TornadoFX 2.0 SNAPSHOT. It shows like expected.

The error you are describing @SKeeneCode sounds rather like a problem with the java modul system. Make sure you are using the open openjfx javafx plugin which will handle these topics conviently for you - or handle it by passing it to the vm-arguments.

SchweinchenFuntik commented 4 years ago

@deggers your example also works with and without a plugin; JavaFX 11

deggers commented 4 years ago

@SchweinchenFuntik yeah - but regarding the modul system it can only work when you got javafx in your classpath :) this can be done via plugin or manually

SKeeneCode commented 4 years ago

@deggers Can I see your use of the plugin in your build file? Mine is:

javafx {
    modules("javafx.controls", "javafx.fxml", "javafx.web", "javafx.graphics")
    version = "13"
}
deggers commented 4 years ago

@SKeeneCode Sure. More or less the same - i just use kotlin for configuration :)

javafx {
    version = "13.0.2"
    modules = mutableListOf("javafx.controls", "javafx.graphics", "javafx.web")
}

Do you really need fxml when you can use the genius typesafe styling methods from Tornado? Here in case you oversaw that Link

Is there a particular reason you ask for the settings? For openFX13 you must use Gradle >= 6.0

SKeeneCode commented 4 years ago

@deggers No particular reason for those settings some of those modules are probably left over from something I played around with months ago xd I was just hoping to see if any difference was causing me to get the original error while it seems fine for you...

Just checked and I am using Gradle wrapper 6.0

SchweinchenFuntik commented 4 years ago

@SKeeneCode if @deggers example works for you, then it is better to throw off the most identical code. If not, maybe there are other nuances.

SchweinchenFuntik commented 4 years ago

also try creating a new project.