Tornadofx Javafx-如何重新加载视图/组件

Tornadofx Javafx-如何重新加载视图/组件,javafx,kotlin,tornadofx,Javafx,Kotlin,Tornadofx,因此,这是一个基本问题。 我试图实现的是从另一个视图刷新视图 假设我有一个视图EmployeeTableView,它通过执行REST API调用来显示员工的表格表示。 在另一个视图中,我有一个过滤器EmployeeFilterView,其中我有性别、薪资范围、员工类型等。 我还有一个userContext对象,在其中存储用户首选项。因此,默认情况下,假设我已将性别筛选器的值存储为男性,薪资范围存储为全部,等等。此对象作为参数发送到EmployeeTableView 加载EmployeeTable

因此,这是一个基本问题。
我试图实现的是从另一个视图刷新视图

假设我有一个视图EmployeeTableView,它通过执行REST API调用来显示员工的表格表示。
在另一个视图中,我有一个过滤器EmployeeFilterView,其中我有性别、薪资范围、员工类型等。
我还有一个userContext对象,在其中存储用户首选项。因此,默认情况下,假设我已将性别筛选器的值存储为男性,薪资范围存储为全部,等等。此对象作为参数发送到EmployeeTableView

加载EmployeeTableView时,我使用userContext值执行restAPI调用以获取员工详细信息。这样就行了。现在,我将性别过滤器更改为女性,并在我的userContext中分配此值。
现在,如果我可以用userContext对象重新加载EmployeeTableView,restapi调用将获得更新的值

但我该怎么做呢?

如果有的话,还可以建议一种更好的方法。

我最终使用了Tornadofx->EventBus

基本上,当我更改任何过滤器时,我会触发一个偶数,它使用更新的值重建节点


不确定该方法是否正确,这就是为什么仍然保持开放供讨论的原因。

事件总线是一种有效的解决方案。另一种方法是使用ViewModel或Controller作为UserContext对象,让其包含实际可观察的员工列表,然后将该列表绑定到
EmployeeTableView
中的
TableView
。每当上下文中的列表更新时,TableView也将更新

filter视图将调用UserContext中的函数来执行实际的REST调用,并基于此更新员工列表

您可以创建一个单独的EmployeeQuery对象,该对象可以注入到
EmployeeFilterView
UserContext
中,以便它可以提取所选的筛选值来执行查询。此查询对象包含要传递给服务器的所有搜索参数的列表

您也可以考虑创建一个单独的范围来保持这些组件的分离,如果这对您的体系结构是有意义的。 具体如何定义这些组件主要是一个品味问题,这里有一个建议。我使用ControlsFX中的

范围滑块
来模拟搜索UI

为了更容易地想象这两者是如何联系在一起的,下面是一个屏幕截图:

(所有的名字和薪水都是虚构的:)

/**
*employee域模型,实现JsonModel以便获取
*通过RESTAPI
*/
类雇员:JsonModel{
val nameProperty=SimpleStringProperty()
按名称属性的变量名称
val salaryProperty=SimpleIntegerProperty()
按工资性质划分的var工资
val genderProperty=SimpleObject属性()
按性别属性划分的性别变量
重写fun updateModel(json:JsonObject){
使用(json){
name=getString(“name”)
工资=getInt(“工资”)
gender=gender.valueOf(getString(“gender”))
}
}
}
枚举类性别{男性,女性}
/**
*用于员工列表的容器以及筛选器调用的搜索函数
*在需要更新员工列表时查看。
*/
类EmployeeContext:Controller(){
valapi:Rest by inject()
val查询:EmployeeQuery by inject()
val employees=SimpleListProperty()
趣味搜索(){
运行异步{
FXCollections.observableArrayList(Employee().apply{
name=“Edvin Syse”
性别=性别。男性
工资=200_000
})
//api.post(“雇员/查询”,query).list().toModel()
}用户界面{
employees.value=it
}
}
}
/**
*用于定义发送到服务器的查询的查询对象
*/
类EmployeeQuery:ViewModel(),JsonModel{
val genderProperty=SimpleObject属性(Gender.Female)
按性别属性划分的性别变量
val salaryMinProperty=SimpleIntegerProperty(50_000)
根据salaryMin属性的var salaryMin
val salaryMaxProperty=SimpleIntegerProperty(250_000)
根据salaryMaxProperty计算的var salaryMax
val salaryDescription=stringBinding(salaryMinProperty、salaryMaxProperty){
“$$salaryMin-$$salaryMax”
}
重写json(json:JsonBuilder){
使用(json){
添加(“性别”,gender.toString())
添加(“salaryMin”,salaryMin)
添加(“salaryMax”,salaryMax)
}
}
}
/**
*搜索/筛选界面
*/
类EmployeeFilterView:View(){
val查询:EmployeeQuery by inject()
val context:EmployeeContext by inject()
覆盖val root=form{
字段集(“员工过滤器”){
字段(“性别”){
组合框(query.genderProperty,Gender.values().toList())
}
字段(“薪资范围”){
vbox{
对齐=位置中心
添加(RangeSloider()。应用{
最大值=500_000.0
lowValueProperty()
highValueProperty().BindBidirective(query.salaryMaxProperty)
})
标签(query.salaryDescription)
}
}
按钮(“搜索”)。操作{
context.search()
}
}
}
}
/**
*显示搜索结果的UI
*/
类EmployeeTableView:View(){
val context:EmployeeContext by inject()
覆盖val root=borderpane{
居中{
tableview(context.employees){
列(“名称”,雇员::名称属性)
列(“性别”,雇员::性别属性)
列(“工资”,员工::salaryProperty)
}
}
}
}
/**
*一个示例视图,用于连接f
/**
 * The employee domain model, implementing JsonModel so it can be fetched 
 * via the REST API
 */
class Employee : JsonModel {
    val nameProperty = SimpleStringProperty()
    var name by nameProperty

    val salaryProperty = SimpleIntegerProperty()
    var salary by salaryProperty

    val genderProperty = SimpleObjectProperty<Gender>()
    var gender by genderProperty

    override fun updateModel(json: JsonObject) {
        with (json) {
            name = getString("name")
            salary = getInt("salary")
            gender = Gender.valueOf(getString("gender"))
        }
    }
}

enum class Gender { Male, Female }

/**
 * Container for the list of employees as well as a search function called by the filter
 * view whenever it should update the employee list.
 */
class EmployeeContext : Controller() {
    val api: Rest by inject()
    val query: EmployeeQuery by inject()
    val employees = SimpleListProperty<Employee>()

    fun search() {
        runAsync {
            FXCollections.observableArrayList(Employee().apply {
                name = "Edvin Syse"
                gender = Gender.Male
                salary = 200_000
            })
            //api.post("employees/query", query).list().toModel<Employee>()
        } ui {
            employees.value = it
        }
    }
}

/**
 * Query object used to define the query sent to the server
 */
class EmployeeQuery : ViewModel(), JsonModel {
    val genderProperty = SimpleObjectProperty<Gender>(Gender.Female)
    var gender by genderProperty

    val salaryMinProperty = SimpleIntegerProperty(50_000)
    var salaryMin by salaryMinProperty

    val salaryMaxProperty = SimpleIntegerProperty(250_000)
    var salaryMax by salaryMaxProperty

    val salaryDescription = stringBinding(salaryMinProperty, salaryMaxProperty) {
        "$$salaryMin - $$salaryMax"
    }

    override fun toJSON(json: JsonBuilder) {
        with(json) {
            add("gender", gender.toString())
            add("salaryMin", salaryMin)
            add("salaryMax", salaryMax)
        }
    }
}

/**
 * The search/filter UI
 */
class EmployeeFilterView : View() {
    val query: EmployeeQuery by inject()
    val context: EmployeeContext by inject()

    override val root = form {
        fieldset("Employee Filter") {
            field("Gender") {
                combobox(query.genderProperty, Gender.values().toList())
            }
            field("Salary Range") {
                vbox {
                    alignment = Pos.CENTER
                    add(RangeSlider().apply {
                        max = 500_000.0
                        lowValueProperty().bindBidirectional(query.salaryMinProperty)
                        highValueProperty().bindBidirectional(query.salaryMaxProperty)
                    })
                    label(query.salaryDescription)
                }
            }
            button("Search").action {
                context.search()
            }
        }
    }
}

/**
 * The UI that shows the search results
 */
class EmployeeTableView : View() {
    val context: EmployeeContext by inject()

    override val root = borderpane {
        center {
            tableview(context.employees) {
                column("Name", Employee::nameProperty)
                column("Gender", Employee::genderProperty)
                column("Salary", Employee::salaryProperty)
            }
        }
    }
}

/**
 * A sample view that ties the filter UI and result UI together
 */
class MainView : View("Employee App") {
    override val root = hbox {
        add(EmployeeFilterView::class)
        add(EmployeeTableView::class)
    }
}