我有以下组件:
class ChildModel:ViewModel() { //or it may be an POJO, it does not matter
val value ....
}
class ParentView: View() {
...
//Maybe this should be implemented into ParentViewModel
val childrenList:List<ChildModel>
fun addFragmentAsChild() {
//should:
// 1. display fragment within ParentView
// 2. add fragment into modelList (or fragmentList - it does not matter - important to have access to the model of every child )
}
fun deleteFragmentAsChild() {
//should destroy child and remove item from childrenList
//should work also on manual closing
}
}
class ChildFragment: Fragment() {
val model = ChildModel()
...
}
总结:我想创建MDI,并且可以访问每个孩子的模型。
我尝试用帮助&#34; openInternalWindow&#34; ,但我无法创建多个子实例,我必须手动管理列表 - 这很糟糕。
class InstrumentsView: View() {
override val root = BorderPane()
val instrumentList = ArrayList<InstrumentFragment>()
init {
with(root){
top = menubar {
menu("Tools") {
menuitem("Add instrument", "Shortcut+A") {
val newFragment = InstrumentFragment()
instrumentList.add(newFragment)
println(instrumentList.size)
openInternalWindow(newFragment, modal = false)
}
}
}
}
}
}
如何正确地使用tornadofx方式?
答案 0 :(得分:3)
在这个例子中,我将使用视图模型和范围来跟踪每个乐器编辑器的项目。我们需要确保这些工具是唯一的,因此我们可以在编辑器关闭时将它们从列表中删除。我创建了一个带有id和名称的Instrument
域对象:
class Instrument {
val idProperty = SimpleObjectProperty<UUID>(UUID.randomUUID())
var id by idProperty
val nameProperty = SimpleStringProperty()
var name by nameProperty
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Instrument
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id.hashCode()
}
}
我们想要一个可以在仪器编辑器中注入的视图模型。我们将确保默认情况下视图模型包含新工具。它包含name属性的外观,因此我们可以将它绑定到编辑器输入字段。
class InstrumentModel: ItemViewModel<Instrument>() {
init {
item = Instrument()
item.name = "New instrument"
}
val name = bind { item?.nameProperty }
}
Fragment
有onDock
和onUndock
的回调,可用于跟踪该片段的模型。我们可以使用事件来表明这一点。声明以下事件:
class InstrumentAdded(val instrument: Instrument) : FXEvent()
class InstrumentRemoved(val instrument: Instrument) : FXEvent()
覆盖InstrumentFragment
中的停靠回调以触发这些事件:
override fun onDock() {
fire(InstrumentAdded(model.item))
}
override fun onUndock() {
fire(InstrumentRemoved(model.item))
}
现在我们将在主视图中保留工具列表InstrumentsView
。这也可以是Controller
。
val instruments = FXCollections.observableArrayList<Instrument>()
在主视图的init类中,我们将订阅我们创建的事件并修改我们的列表:
subscribe<InstrumentAdded> {
instruments.add(it.instrument)
}
subscribe<InstrumentRemoved> {
instruments.remove(it.instrument)
}
“新仪器”操作将在新的Scope
中打开一个新的InstrumentEditor,这样我们就可以将视图模型注入其中并获得该编辑器唯一的实例。
menuitem("Add instrument", "Shortcut+A") {
find<InstrumentFragment>(Scope()).openWindow()
}
不幸的是,我们无法使用openInternalWindow
,因为它目前一次只支持一个内部窗口。因此,我改为使用openWindow
。
如果要从操作中关闭编辑器,可以从片段内的任何位置调用closeModal()
。
我已经包含了一个带有TableView的完整示例应用程序,该应用程序显示了当前打开的乐器。它将如下图所示。请注意,在从模型中刷新更改并在表中可见之前,需要单击“保存”。
我希望这是您正在寻找的,或者您至少可以根据此示例修改它以适合您的用例。
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import tornadofx.*
import java.util.*
class Instrument {
val idProperty = SimpleObjectProperty<UUID>(UUID.randomUUID())
var id by idProperty
val nameProperty = SimpleStringProperty()
var name by nameProperty
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Instrument
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id.hashCode()
}
}
class InstrumentModel : ItemViewModel<Instrument>() {
init {
item = Instrument()
item.name = "New instrument"
}
val name = bind { item?.nameProperty }
}
class InstrumentAdded(val instrument: Instrument) : FXEvent()
class InstrumentRemoved(val instrument: Instrument) : FXEvent()
class InstrumentFragment : Fragment("Instrument Editor") {
val model: InstrumentModel by inject()
override val root = form {
prefWidth = 300.0
fieldset("Edit instrument") {
field("Name") {
textfield(model.name)
}
}
button("Save") {
setOnAction {
model.commit()
}
}
}
override fun onDock() {
fire(InstrumentAdded(model.item))
}
override fun onUndock() {
fire(InstrumentRemoved(model.item))
}
}
class InstrumentsView : View() {
val instruments = FXCollections.observableArrayList<Instrument>()
override val root = borderpane {
setPrefSize(400.0, 300.0)
top {
menubar {
menu("Tools") {
menuitem("Add instrument", "Shortcut+A") {
find<InstrumentFragment>(Scope()).openWindow()
}
}
}
}
center {
tableview(instruments) {
column("Name", Instrument::nameProperty)
columnResizePolicy = SmartResize.POLICY
}
}
}
init {
subscribe<InstrumentAdded> {
instruments.add(it.instrument)
}
subscribe<InstrumentRemoved> {
instruments.remove(it.instrument)
}
}
}