Search code examples
kotlintornadofx

Change the value of a property of some data, but tableview doesn't update


For a very simple table demo of TornadoFX, I just want to show some users in a view, and changes the names of them when clicking on a change button. But the problem is the modified data is not shown in table.

The main code is as following:

class User2(id: Int, name: String) {
    val idProperty = SimpleIntegerProperty(id)
    var id by idProperty

    val nameProperty = SimpleStringProperty(name)
    var name by nameProperty
}

val data2 = listOf(User2(111, "AAA"), User2(222, "BBB"), User2(333, "CCC")).observable()

vbox {
    tableview(data2) {
        column("id", User2::id)
        column("name", User2::name).minWidth(200)
    }
    button("Modify data with type of User2").setOnAction {
        data2.forEach { it.name += " changed!" }
    }
}

Instead, if I define the User2 as following (also changed the class name to User1):

class User1(id: Int, name: String) {
    val id = SimpleIntegerProperty(id)
    val name = SimpleStringProperty(name)
}

Everything is working well.

I can't find why the first one is not working (as the code is most copied form the official guide)

Update:

A complete small demo to represent this question: https://github.com/javafx-demos/tornadofx-table-property-change-issue-demo


Solution

  • It looks like this issue is caused by confusing naming :-)

    When refactoring User2 and renaming some fields it becomes evident that you were using the String and Int fields instead of the StringProperty and IntegerProperty, which obviously don't support binding.

    If User2 looks like following:

    class User2(id: Int, name: String) {
        val idProperty = SimpleIntegerProperty(id)
        var myId by idProperty
    
        val nameProperty = SimpleStringProperty(name)
        var myName by nameProperty
    }
    

    And the code changing it like following:

    vbox {
        tableview(data2) {
            column("myId", User2::myId)
            column("myName", User2::nameProperty).minWidth(200)
        }
        button("Modify data with type of User2").setOnAction {
            data2.forEach { it.myName += " changed!" }
        }
    }
    

    Everything seems to be working fine. As you can see before you were changing only the Int and String fields which doesn't lead to any updates.