import javafx.animation.AnimationTimer import javafx.collections.FXCollections import javafx.scene.paint.Color import javafx.scene.shape.Rectangle import javafx.util.Duration import tornadofx.* import kotlin.collections.ArrayList class LearnApp : App(LearnV::class) class LearnV : View("learn 選擇排序") { // 每一個矩形寬度 val w = 6.0 // 100個矩形容器 val rec = FXCollections.observableArrayList<Rectangle>() // 動畫計時器 val aniTimer = AniTimer(this) val result = stringProperty() val N = 100 val randomBound = 200 val data0 = SelectionSortData(N, randomBound) override val root = borderpane { top = vbox(5) { result.value = "result:${data0.numbers.toString()}" label(result) { isWrapText = true } hbox(5) { button("run").action { // ani() aniTimer.start() } button("stop").action { // ani() aniTimer.stop() } } } center = group { (1..N).forEach{ val r = rectangle(w * it, 200.0, w - 2, data0.numbers[it - 1]) { fill = Color.BLUE } rec.add(r) } } center.rotate=180.0 prefHeight = 800.0 prefWidth = 1000.0 } fun paint() { timeline { keyframe(Duration.seconds(0.0010)) { for (i in data0.numbers.indices) { var minIndex = i var j = i + 1 if (j < data0.N()) { (j..data0.N()).map { if (data0.get(j) < data0.get(minIndex)) { minIndex = j } } } data0.swap(i, minIndex) keyvalue(rec[i].heightProperty(), data0.numbers[i]) result.value = "result:${data0.numbers.toString()}" } } } } // 此方法能夠中止動畫 class AniTimer(val learnV: LearnV) : AnimationTimer() { var lastTime = 0L override fun handle(now: Long) { if ((now - lastTime) > 10000000) { lastTime = now } else { return } learnV.paint() } } } class SelectionSortData { val numbers = ArrayList<Int>() constructor(N: Int, randomBound: Int) { (1..N).map { numbers.add((1..randomBound).random()) } } fun N() = numbers.size fun get(i: Int) = numbers[i] fun swap(i: Int, j: Int) { val t = numbers[i] numbers[i] = numbers[j] numbers[j] = t } }