繁体   English   中英

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

[英]Tornadofx Javafx - How to reload a view / component

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

可以说我有一个EmployeeTableView视图,该视图通过执行REST API调用来显示员工的表格表示形式。
在另一个视图中,我有一个过滤器EmployeeFilterView,其中有性别,薪水范围,员工类型等。
我还有一个userContext对象,用于存储用户首选项。 因此,默认情况下,我已将性别过滤器的值存储为Male,工资范围存储为ALL,等等。该对象作为参数发送到EmployeeTableView。

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

但是我该怎么做呢?
如果有的话,也建议一个更好的方法。

EventBus是对此的一种有效解决方案。 另一种方法是将ViewModel或Controller用作UserContext对象,并让其包括实际可观察​​到的雇员列表,然后将该列表绑定到EmployeeTableViewTableView 每当上下文中的列表更新时,TableView也会更新。

筛选器视图将在UserContext中调用一个函数以执行实际的REST调用,并基于该调用更新员工列表。

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

如果对您的体系结构有意义,您也可以考虑创建一个单独的作用域以使这些组件分离。

究竟如何定义这些组件主要取决于口味,这是一个建议。 我将ControlsFX的RangeSlider用于模拟搜索UI。

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

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

员工应用

/**
 * 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)
    }
}

我最终使用了Tornadofx-> EventBus

基本上,当我更改任何过滤器时,都会触发一个用更新后的值重建Node的even。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM