前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用javafx框架tornadofx演示分形图的绘制

用javafx框架tornadofx演示分形图的绘制

原创
作者头像
用户6167008
修改2019-10-14 17:21:12
8270
修改2019-10-14 17:21:12
举报

用到了kotlin 协程、带方法的枚举类等知识点

代码语言:txt
复制
import javafx.beans.property.SimpleObjectProperty
import javafx.geometry.Orientation
import javafx.scene.canvas.Canvas
import javafx.scene.canvas.GraphicsContext
import javafx.scene.control.TextFormatter
import javafx.scene.control.ToggleGroup
import javafx.scene.paint.Color
import kotlinx.coroutines.*
import tornadofx.*
import kotlin.math.PI
import kotlin.math.max
import kotlin.math.sin

class FractalApp : App(FractalView::class)
class FractalController : Controller() {

    val v by inject<FractalView>()
    val canvas0 = v.canvas0

   fun draw(fs: FractalShape1)= GlobalScope.launch {
       canvas0.graphicsContext2D.clearRect(0.0, 0.0, canvas0.width, canvas0.height)
       fs.drawFractal(canvas0.graphicsContext2D,
               v.x.value,
               v.y.value,
               v.widthh.value.toDouble(),
               v.heightt.value.toDouble(),
               v.depth.value,
               v.maxDepth.value,
               v.color.value)
   }
}

class FractalView : View("分形图动画演示") {
    val c by inject<FractalController>()
    val fractal = SimpleObjectProperty(this, "fractal", FractalShape1.Rectangle)
    val x = doubleProperty()
    val y = doubleProperty()
    val widthh = intProperty(700)
    val heightt = intProperty(600)
    val depth = intProperty(4)
    val maxDepth = intProperty(6)
    val color = SimpleObjectProperty(this, "color", MyColor1.Indigo)

    lateinit var canvas0: Canvas
    lateinit var shapeGoup: ToggleGroup

    // 过滤输入,只能输入1以上的正整数
    val firstTenFilter: (TextFormatter.Change) -> Boolean = { change ->
        !change.isAdded || change.controlNewText.let {
            it.isInt() && it.toInt() in 1..Int.MAX_VALUE
        }
    }
    override val root = borderpane {
        style = "-fx-font-size: 14pt; "
        right = vbox(5) {
            prefWidth=300.0
            form {
                fieldset(labelPosition = Orientation.HORIZONTAL) {
                    vbox(5) {
                        field("x:") {
                            textfield(x) {
                                text = "10"
                                filterInput(firstTenFilter)
                            }
                        }
                        field("y:") {
                            textfield(y) {
                                text = "10"
                                filterInput(firstTenFilter)
                            }
                        }
                        field("widthh:") {
                            spinner(100, 1000, 400, 100, false, widthh)
                        }
                        field("heightt:") {
                            spinner(100, 1000, 400, 100, false, heightt)
                        }
                        field("depth:") {
                            spinner(1, 10, 4, 1, false, depth)
                        }
                        field("maxDepth:") {
                            spinner(1, 10, 4, 1, false, maxDepth)
                        }
                    }
                    vbox(5) {
                        field("color:") {
                            combobox(property = color, values = MyColor1.all) {
                                selectionModel.selectedItemProperty().addListener { _, _, _ ->
                                    c.draw(fractal.value)
                                }
                            }
                        }
                        field("depth:") {
                            slider(1, 10, 4) {
                                isShowTickLabels = true
                                isShowTickMarks = true
                                valueProperty().bindBidirectional(depth)
                            }
                        }
                        field("maxDepth:") {
                            slider(1, 10, 6) {
                                isShowTickLabels = true
                                isShowTickMarks = true
                                valueProperty().bindBidirectional(maxDepth)
                            }
                        }

                        shapeGoup = togglegroup {
                            FractalShape1.values().forEach { fs ->
                                radiobutton(fs.name) {
                                    action {
                                        // 实现ToggleGroup与combobox联动
                                        fractal.value = fs
                                        c.draw(fs)
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        center = stackpane {
            canvas0 = canvas(800.0, 700.0)
            paddingAll = 10
        }
    }
}

enum class MyColor1(val color: Color) {
    Red(Color.RED), Blue(Color.BLUE), Indigo(Color.INDIGO), Yellow(Color.YELLOW);

    companion object {
        val all by lazy { values().toList() }
    }
}

//分形形状,矩形、圆、椭圆
enum class FractalShape1 {
    Rectangle {
        override suspend fun drawFractal(g: GraphicsContext, x: Double, y: Double, w: Double, h: Double, depth: Int, maxDepth: Int, color: MyColor1) {
            g.fill = color.color
            if (depth == maxDepth) {
                g.fillRect(x, y, w, h)
                return
            }
            if ((w <= 1).and(h <= 1)) {
                g.fillRect(x, y, max(w, 1.0), max(h, 1.0))
                return
            }
            val w_3 = w / 3
            val h_3 = h / 3
            delay(delay0)
            drawFractal(g, x, y, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)

            drawFractal(g, x + 2 * w_3, y, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)

            drawFractal(g, x + w_3, y + h_3, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)

            drawFractal(g, x, y + 2 * h_3, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)

            drawFractal(g, x + 2 * w_3, y + 2 * h_3, w_3, h_3, depth + 1, maxDepth, color)
            return
        }
    },
    Circle {
        override suspend fun drawFractal(g: GraphicsContext, x: Double, y: Double, w: Double, h: Double, depth: Int, maxDepth: Int, color: MyColor1) {
            g.fill = color.color

            if (depth == maxDepth) {
                g.fillOval(x, y, w, w)
                return
            }
            if (w <= 1) {
                g.fillOval(x, y, max(w, 1.0), max(w, 1.0))
                return
            }

            val w_3 = w / 3
            val h_3 = h / 3
            delay(delay0)

            drawFractal(g, x, y, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x + 2 * w_3, y, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x + w_3, y + h_3, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x, y + 2 * h_3, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x + 2 * w_3, y + 2 * h_3, w_3, h_3, depth + 1, maxDepth, color)
            return
        }
    },
    Triangle {
        override suspend fun drawFractal(g: GraphicsContext, x: Double, y: Double, w: Double, h: Double, depth: Int, maxDepth: Int, color: MyColor1) {
            var side = w
            val y=y-20
            if (side <= 1) {
                Rectangle.drawFractal(g, x, y, 1.0, 1.0, depth, maxDepth, color)
                return
            }

            val bx = x + side
            val by = y
            val h = sin(60 * PI / 180) * side

            val cx = x + side / 2
            val cy = y - h
            if (depth == maxDepth) {
                drawTriangle(g, x, y, bx, by, cx, cy, color)
                return
            }

            val ab_centerx = (x + bx) / 2
            val ab_centery = (y + by) / 2
            val ac_centerx = (x + cx) / 2
            val ac_centery = (y + cy) / 2

            delay(delay0)

            // 左下角三角形
            drawFractal(g, x, y, w / 2, h, depth + 1, maxDepth, color)
            delay(delay0)
// 上三角形
            drawFractal(g, ac_centerx, ac_centery, w / 2, h, depth + 1, maxDepth, color)
            delay(delay0)
// 右下角三角形
            drawFractal(g, ab_centerx, ab_centery, w / 2, h, depth + 1, maxDepth, color)
        }
    },
    Ellipse {
        override suspend fun drawFractal(g: GraphicsContext, x: Double, y: Double, w: Double, h: Double, depth: Int, maxDepth: Int, color: MyColor1) {
            g.fill = color.color
            if (depth == maxDepth) {
                g.fillOval(x, y, w, h)
                return
            }
            if ((w <= 1).and(h <= 1)) {
                g.fillOval(x, y, max(w, 1.0), max(h, 1.0))
                return
            }
            delay(delay0)

            val w_3 = w / 3
            val h_3 = h / 3*0.8
            drawFractal(g, x, y, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x + 2 * w_3, y, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x + w_3, y + h_3, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x, y + 2 * h_3, w_3, h_3, depth + 1, maxDepth, color)
            delay(delay0)
            drawFractal(g, x + 2 * w_3, y + 2 * h_3, w_3, h_3, depth + 1, maxDepth, color)
            return
        }
    };

    companion object {
        val delay0=100L
        val all by lazy { values().toList() }
    }

    fun drawTriangle(g: GraphicsContext, ax: Double, ay: Double, bx: Double, by: Double, cx: Double, cy: Double, color: MyColor1) {
        g.fill = color.color
        g.strokePolygon(doubleArrayOf(ax, bx, cx, ax), doubleArrayOf(-ay, -by, -cy, -ay), 3)
    }

    abstract suspend fun drawFractal(g: GraphicsContext, x: Double, y: Double, w: Double, h: Double, depth: Int, maxDepth: Int, color: MyColor1)
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档