Javafx Tornadofx-如何将参数传递给每个实例上的片段
我是javafx、kotlin和tornadofx的新手。Javafx Tornadofx-如何将参数传递给每个实例上的片段,javafx,kotlin,tornadofx,Javafx,Kotlin,Tornadofx,我是javafx、kotlin和tornadofx的新手。 问题: 如何将参数传递给每个实例上的片段 假设我有一个表视图布局作为我的片段。现在,这个片段在多个地方使用,但数据集不同 例如。 在中添加一个片段: class SomeView : View() { ... root += SomeViewFragment::class } class SomeAnotherView : View() { ... root += SomeViewFragment::class } 声明片段:
问题:
如何将参数传递给每个实例上的片段 假设我有一个表视图布局作为我的片段。现在,这个片段在多个地方使用,但数据集不同 例如。 在中添加一个片段:
class SomeView : View() {
...
root += SomeViewFragment::class
}
class SomeAnotherView : View() {
...
root += SomeViewFragment::class
}
声明片段:
class SomeViewFragment : Fragment() {
...
tableview(someDataSetFromRestApiCall) {
...
}
}
如何从restapicall到SomeView和SomeAnotherView传递不同的somedataset?让我们从向片段传递数据的最显式方式开始。对于这个TableView示例,您可以在片段中公开一个可观察列表,并将您的TableView绑定到此列表。然后,您可以从片段外部更新该列表,并在片段中反映您的更改。例如,我创建了一个简单的数据对象,它具有一个名为
SomeItem
的可观察属性:
class SomeItem(name: String) {
val nameProperty = SimpleStringProperty(name)
var name by nameProperty
}
现在,我们可以使用绑定到TableView的item属性定义SomeViewFragment
:
class SomeViewFragment : Fragment() {
val items = FXCollections.observableArrayList<SomeItem>()
override val root = tableview(items) {
column("Name", SomeItem::nameProperty)
}
}
虽然这很容易理解并且非常明确,但它在组件之间创建了非常强的耦合。您可能需要考虑使用作用域来代替此。我们现在有两个选择:
class ItemsModel(val items: ObservableList<SomeItem>) : ViewModel()
最后,我们需要为每个视图中的片段定义一个单独的范围,并为该范围准备数据:
class SomeView : View() {
override val root = stackpane {
// Create the model and fill it with data
val model= ItemsModel(listOf(SomeItem("Item A"), SomeItem("Item B")).observable())
// Define a new scope and put the model into the scope
val fragmentScope = Scope()
setInScope(model, fragmentScope)
// Add the fragment for our created scope
this += find<SomeViewFragment>(fragmentScope)
}
}
让作用域包含数据
另一种选择是将数据直接放入范围。让我们创建一个itemscope
:
class ItemsScope(val items: ObservableList<SomeItem>) : Scope()
视图现在需要做的工作更少,因为我们不需要模型:
class SomeView : View() {
override val root = stackpane {
// Create the scope and fill it with data
val itemsScope= ItemsScope(listOf(SomeItem("Item A"), SomeItem("Item B")).observable())
// Add the fragment for our created scope
this += find<SomeViewFragment>(itemsScope)
}
}
SomeViewFragment
现在可以拾取这些参数并直接使用它们:
class SomeViewFragment : Fragment() {
val items: ObservableList<SomeItem> by param()
override val root = tableview(items) {
column("Name", SomeItem::nameProperty)
}
}
class-SomeViewFragment:Fragment(){
val项:按参数()列出的ObservableList
覆盖val root=tableview(项){
列(“名称”,SomeItem::nameProperty)
}
}
请注意,这不涉及片段内部未经检查的强制转换
其他选择
您还可以通过EventBus传递参数和数据,EventBus也将在即将发布的TornadoFX 1.5.9中。EventBus还支持作用域,使您可以轻松地确定事件的目标
进一步阅读
您可以在指南中阅读有关作用域、EventBus和ViewModel的更多信息:
由于这个问题,我们现在讨论是否应该在组件中添加对参数的支持,有点像HTTP请求参数,使在视图、片段甚至控制器之间传递消息更加方便:)我们刚刚添加了params选项,我更新了上面的答案。哇!!谢谢你这么好的解释。我刚刚实现了“在范围内使用注入”部分,它工作起来很有魅力。我赞扬你们做了如此出色的工作,提供了即时支持和帮助。谢谢Edvin和团队:)@mercy123如果您还有任何问题或想法,请随时加入我们的#tornadofx Slack频道。我们欢迎因人们的需要而产生的新特性。
FX.getComponents(fragmentScope).put(ItemsModel::class, model)
class ItemsScope(val items: ObservableList<SomeItem>) : Scope()
class SomeViewFragment : Fragment() {
override val scope = super.scope as ItemsScope
override val root = tableview(scope.items) {
column("Name", SomeItem::nameProperty)
}
}
class SomeView : View() {
override val root = stackpane {
// Create the scope and fill it with data
val itemsScope= ItemsScope(listOf(SomeItem("Item A"), SomeItem("Item B")).observable())
// Add the fragment for our created scope
this += find<SomeViewFragment>(itemsScope)
}
}
class SomeView : View() {
override val root = stackpane {
val params = "items" to listOf(SomeItem("Item A"), SomeItem("Item B")).observable()
this += find<SomeViewFragment>(params)
}
}
class SomeViewFragment : Fragment() {
val items: ObservableList<SomeItem> by param()
override val root = tableview(items) {
column("Name", SomeItem::nameProperty)
}
}