在此示例中,我将使用视图模型和范围来跟踪每个仪器编辑器的项目。我们需要确保这些工具是唯一的,以便我们可以在编辑器关闭时将它们从列表中删除。我创建了一个Instrument
带有 id 和名称的域对象:
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 }
}
AFragment
具有回调,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)
}
“New Instrument” 操作将在新的 InstrumentEditor 中打开一个新的 InstrumentEditor,Scope
这样我们就可以将视图模型注入其中并获得该编辑器唯一的实例。
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)
}
}
}