tornadofx使用rectangle、AnimationTimer、timeline动画演示选择排序,第2版-LMLPHP


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
    }
}
07-18 11:20