有关Kotlin的一些基本问题

时间:2019-06-12 17:44:36

标签: kotlin tornadofx

我正在尝试学习Kotlin和TornadoFX,并且正在this repository上工作

当前的想法是该应用将显示3行的7个按钮。每个按钮代表一个已知或未知的字母。如果知道该字母,该字母将显示在按钮上。如果字母未知,该按钮将显示索引(0-20)。

我通过创建(确定使用Java来确定)具有21个元素的全局数组来做到这一点。每个元素都以null开头。我在主应用程序中使用伴随结构定义了此代码:

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
                        }
                    }

我要说的是:“如果元素值不为null,则使用元素值,否则使用index的字符串值。这不起作用,因为按钮仅在其上具有索引,从不字母。

我注意到,如果我没有在元素上使用.toString(),则会收到一个错误,提示按钮期望使用String而不是String?这似乎有点类似于Java和String与Optional 。但是,当我添加toString()时,会收到IDE警告toString()是多余的。

如果我脱掉尾随的?总共,我得到了一个干净的编译器,但是仍然只渲染了三个按钮,它们的标签是索引,而不是元素。

所以我很确定自己在此过程中迷路了,有人可以解释为什么我的程序无法正常工作吗?

此外,在调试应用程序时,我总是会经历两个过程。我不明白为什么,但这是IntelliJ的样子:

enter image description here

这正常吗?

1 个答案:

答案 0 :(得分:2)

您的init函数正在运行,您可以通过将条目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库的“块式”方法将21个大小的数组划分为三个大小为7的列表。然后可以遍历(您必须使用这种方法将显示索引拼凑起来)以创建新行对于每个列表(3个列表构成3行),同时在该行的lambda内的嵌套循环中创建按钮。

这里要摘录的关键是,并不是在{} lambda行中添加了所有按钮。

对于双重处理问题,如果我使用类似这样的主要方法运行应用程序,则不会出现此问题:

fun main(args: Array<String>) {
    launch<InteractiveClientApp>(args)
}

希望这会有所帮助!