Ответ:
Вам необходимо понять 3 вещи:
1. Kotlin Упрощение Java Получение / установка - Это просто. Kotlin делает эту замечательную вещь, когда он распознает, что он использует класс Java и что член в этом классе имеет функции установщика / получателя, он позволит вам получить доступ к этим членам, как если бы это была прямая ссылка. Так, например, button.setText("some text");
теперь становится button.text = "some text"
.
2. Функции компоновщика TornadoFX - Допустим, вы наведите курсор мыши на form
в вашей IDE. Вы заметите, что функция включает op: Form.() → Unit
в свои параметры. Это означает, что когда вы прикрепляете скобки к form
, например:
field {
//here is some code
}
, тогда все, что находится внутри этих скобок, изменит получателя на созданный Form
вместо AsyncView
. Поэтому, когда вы упомянули text
в textfield(text)
, вы в конечном итоге ссылались на текст, принадлежащий объекту Field
. Когда вы писали controller.performWrite(text)
, вы в конечном итоге ссылались на текст, принадлежащий объекту Button
и т. Д.
3. Kotlin Block Scopes - Как упомянуто выше, блоки могут иметь возможность менять свой получатель. Тем не менее, это не мешает вам ссылаться на члены / функции вне себя. Вы просто назвали его так же, и приоритет ссылки вызвал проблему. Вы можете исправить это, просто изменив текстовый элемент на другое имя, или:
override val root = form {
fieldset {
field("Current Input") {
textfield(this@AsyncView.text)
}
label(llabel)
button("Commit") {
action {
runAsync {
controller.performWrite(this@AsyncView.text.value)
this@AsyncView.text.value = ""
} ui {
llabel.value = controller.getValue()
}
}
}
}
}
Используйте явные теги для this
.
Улучшение:
ПОЖАЛУЙСТА, посмотрите на все мои комментарии. Это все еще не охватывает все, что вы можете сделать с мощью TornadoFX и Kotlin, но это только начало. Также: удалите все эти точки с запятой !!!
class AsyncView : View() {
val controller: AsyncController by inject()
val inputProperty = SimpleStringProperty() //Name is descriptive and appropriate to its role
var input by inputProperty //TornadoFX-unique way to get/set property values
val valueLabelTextProperty = SimpleStringProperty("No Commit") //Name is descriptive and appropriate to its role
var valueLabelText by valueLabelTextProperty
override val root = form {
fieldset {
field("Current Input") {
textfield(inputProperty)
}
label(valueLabelTextProperty)
button("Commit") {
action {
runAsync {
controller.performWrite(input)
input = ""
controller.myValue //The last line's value gets passed to success block. Leave as little work to UI as possible
} success { value -> // ui is only included for backwards compatibility. success is replacement.
valueLabelText = value
}
}
}
}
}
}
class AsyncController : Controller() {
var myValue: String = "" //Naming should be camel-cased
private set //No need for old-school Java getters/setters. Simply private the set. Look into Kotlin get/set for more info
//If you do not plan to do more than change `myValue` in the future with this method,
//delete it and remove private set from `myValue`. You can use custom Kotlin getters/setters instead.
fun performWrite(inputValue: String) {
myValue = inputValue
}
}