关于Kotlin的一些基本问题
Some basic questions about Kotlin
我正在尝试学习 Kotlin 和 TornadoFX,我在 this repository
工作
目前的想法是该应用程序将显示三行,每行 7 个按钮。每个按钮代表一个已知或未知的字母。如果字母已知,它会显示在按钮上。如果字母未知,则按钮显示索引 (0-20)。
我通过创建(使用 Java 认为我确定)一个包含 21 个元素的全局数组来做到这一点。每个元素开始时都是空的。我在主应用程序中使用伴随结构定义了它:
class InteractiveClientApp : App(MainView::class) {
companion object {
var knownLetters = arrayOfNulls<String>(21)
}
然后在 App 构造函数中,我用值初始化了一些随机元素,只是为了看看这是否可行(它不可行)。
override fun init() {
knownLetters[4] = "T"
knownLetters[9] = "G"
knownLetters[17] = "Z"
}
然后在 LettersGridView 中,我在 knownLetters 数组上使用 forEachIndexed,这样我就可以访问数组中的元素及其索引。
import jcn.deduce.client.InteractiveClientApp.Companion.knownLetters
class LettersGridView : View() {
override val root = gridpane {
knownLetters.forEachIndexed { index, element ->
if (index == 0 || index % 7 == 0) {
row {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
} else {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
}
}
}
实际发生的是出现了三个按钮,而不是预期的 21 个,并且按钮上的值始终是索引,而不是字母值。此外,显示的索引是 20、7 和 14。不是我在设置数组中的元素时使用的三个。所以我在那里遗漏了一些东西。
另外我想我没有正确理解这一点:
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
我想说的是“如果元素值不为空,则使用元素值,否则使用索引的字符串值。这是行不通的,因为按钮上只有索引,从不字母。
我注意到如果我在元素上不使用 .toString(),我会收到一个错误,提示按钮需要字符串,而不是字符串?。这似乎有点类似于 Java 和 String vs Optional < String >。但是,当我添加 toString() 时,我收到一个 IDE 警告,指出 toString() 是多余的。
如果我去掉尾随?总的来说,我得到了一个干净的编译,但仍然只有三个按钮呈现,并且它们的标签是索引,而不是元素。
所以我很确定我在某个地方迷路了,谁能解释为什么我的程序不工作?
此外,当我调试应用程序时,我总是以两个进程结束。我不明白为什么,但这就是 IntelliJ 的样子:
这正常吗?
您的初始化函数正在运行,您可以通过将条目 20、7 或 14 的初始化更改为一个字母来确认这一点,您应该会在接下来 运行 它时看到一个字母出现。
至于您的主要问题,您看到 20、7 和 14 的原因是因为在本节中:
if (index == 0 || index % 7 == 0) {
row {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
}
您正在添加带有单个按钮的行,这些按钮将是 0、7 和 14(因为它们都是 == 0 % 7)。这意味着您只会添加三行,每行都有一个按钮。您可能对为什么它说的是 20 而不是 0 感到困惑...嗯,这是因为下一节:
else {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
也在添加按钮,但不添加到任何行(注意这些按钮不在行 { } lambda 内)。这意味着所有这些按钮都将被添加到彼此顶部的网格窗格中,包括第一个 0 按钮。要添加的最后一个按钮是 20,因此为什么你看到 20,它覆盖了 0!
下面是一个如何解决这个问题的例子:
val rowSize = 7
val rows = knownLetters.toList().chunked(rowSize)
rows.forEachIndexed { rowIndex, elements ->
row {
elements.forEachIndexed { buttonIndex, element ->
val displayIndex = rowSize * rowIndex + buttonIndex
button("${element ?: displayIndex}") {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
}
}
这采用 Kotlin 库的 "chunked" 方法将 21 大小的数组分成三个大小为 7 的列表。然后您可以循环遍历(您必须使用这种方法拼凑显示索引)为每个列表创建一个新行(3 个列表构成 3 行),同时在行的 lambda 内的嵌套循环中创建按钮。
这里要注意的关键是,并不是所有的按钮都被添加到一行 { } lambda 中。
至于双进程问题,如果我运行应用程序使用像这样的主要方法,我就没有这个问题:
fun main(args: Array<String>) {
launch<InteractiveClientApp>(args)
}
希望对您有所帮助!
我正在尝试学习 Kotlin 和 TornadoFX,我在 this repository
工作目前的想法是该应用程序将显示三行,每行 7 个按钮。每个按钮代表一个已知或未知的字母。如果字母已知,它会显示在按钮上。如果字母未知,则按钮显示索引 (0-20)。
我通过创建(使用 Java 认为我确定)一个包含 21 个元素的全局数组来做到这一点。每个元素开始时都是空的。我在主应用程序中使用伴随结构定义了它:
class InteractiveClientApp : App(MainView::class) {
companion object {
var knownLetters = arrayOfNulls<String>(21)
}
然后在 App 构造函数中,我用值初始化了一些随机元素,只是为了看看这是否可行(它不可行)。
override fun init() {
knownLetters[4] = "T"
knownLetters[9] = "G"
knownLetters[17] = "Z"
}
然后在 LettersGridView 中,我在 knownLetters 数组上使用 forEachIndexed,这样我就可以访问数组中的元素及其索引。
import jcn.deduce.client.InteractiveClientApp.Companion.knownLetters
class LettersGridView : View() {
override val root = gridpane {
knownLetters.forEachIndexed { index, element ->
if (index == 0 || index % 7 == 0) {
row {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
} else {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
}
}
}
实际发生的是出现了三个按钮,而不是预期的 21 个,并且按钮上的值始终是索引,而不是字母值。此外,显示的索引是 20、7 和 14。不是我在设置数组中的元素时使用的三个。所以我在那里遗漏了一些东西。
另外我想我没有正确理解这一点:
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
我想说的是“如果元素值不为空,则使用元素值,否则使用索引的字符串值。这是行不通的,因为按钮上只有索引,从不字母。
我注意到如果我在元素上不使用 .toString(),我会收到一个错误,提示按钮需要字符串,而不是字符串?。这似乎有点类似于 Java 和 String vs Optional < String >。但是,当我添加 toString() 时,我收到一个 IDE 警告,指出 toString() 是多余的。
如果我去掉尾随?总的来说,我得到了一个干净的编译,但仍然只有三个按钮呈现,并且它们的标签是索引,而不是元素。
所以我很确定我在某个地方迷路了,谁能解释为什么我的程序不工作?
此外,当我调试应用程序时,我总是以两个进程结束。我不明白为什么,但这就是 IntelliJ 的样子:
这正常吗?
您的初始化函数正在运行,您可以通过将条目 20、7 或 14 的初始化更改为一个字母来确认这一点,您应该会在接下来 运行 它时看到一个字母出现。
至于您的主要问题,您看到 20、7 和 14 的原因是因为在本节中:
if (index == 0 || index % 7 == 0) {
row {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
}
您正在添加带有单个按钮的行,这些按钮将是 0、7 和 14(因为它们都是 == 0 % 7)。这意味着您只会添加三行,每行都有一个按钮。您可能对为什么它说的是 20 而不是 0 感到困惑...嗯,这是因为下一节:
else {
button(element?.toString() ?: index.toString()) {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
也在添加按钮,但不添加到任何行(注意这些按钮不在行 { } lambda 内)。这意味着所有这些按钮都将被添加到彼此顶部的网格窗格中,包括第一个 0 按钮。要添加的最后一个按钮是 20,因此为什么你看到 20,它覆盖了 0!
下面是一个如何解决这个问题的例子:
val rowSize = 7
val rows = knownLetters.toList().chunked(rowSize)
rows.forEachIndexed { rowIndex, elements ->
row {
elements.forEachIndexed { buttonIndex, element ->
val displayIndex = rowSize * rowIndex + buttonIndex
button("${element ?: displayIndex}") {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
}
}
}
}
}
这采用 Kotlin 库的 "chunked" 方法将 21 大小的数组分成三个大小为 7 的列表。然后您可以循环遍历(您必须使用这种方法拼凑显示索引)为每个列表创建一个新行(3 个列表构成 3 行),同时在行的 lambda 内的嵌套循环中创建按钮。
这里要注意的关键是,并不是所有的按钮都被添加到一行 { } lambda 中。
至于双进程问题,如果我运行应用程序使用像这样的主要方法,我就没有这个问题:
fun main(args: Array<String>) {
launch<InteractiveClientApp>(args)
}
希望对您有所帮助!