Cómo build el patrón de constructor alnetworkingedor de los componentes de JavaFX en Kotlin

Estoy intentando crear un patrón de construcción en Kotlin para los componentes de javafx. El patrón se verá a continuación

fun main(args: Array<String>) { val vb = vbox { child { hbox { child { label { prefWidth = 20.0 } button { text = "Click" } } } label { prefHeight = 80.0 } } } } 

Lo que he hecho hasta ahora es el siguiente, pero el child no está exponiendo la label ni los methods de los button declarados en Child class Child . ¿Alguna sugerencia?

 fun Pane.child(init: (Pane.() -> Unit)? = null): Child { val ch = Child() init?.invoke(this) ch.parent = this return ch } class Child { var parent: Pane? = null fun <T : Node> initChildNode(styleClass: String? = null, tag: T, init: (T.() -> Unit)? = null): T { init?.invoke(tag) tag.styleClass.add(styleClass) parent?.children?.add(tag) return tag } fun region(styleClass: String? = null, init: (Region.() -> Unit)? = null) = initChildNode(styleClass, Region(), init) fun vbox(styleClass: String? = null, init: (VBox.() -> Unit)? = null) = initChildNode(styleClass, VBox(), init) fun hbox(styleClass: String? = null, init: (HBox.() -> Unit)? = null) = initChildNode(styleClass, HBox(), init) fun label(styleClass: String? = null, init: (Label.() -> Unit)? = null) = initChildNode(styleClass, Label(), init) fun button(styleClass: String? = null, init: (Button.() -> Unit)? = null) = initChildNode(styleClass, Button(), init) } fun vbox(styleClass: String? = null, init: (VBox.() -> Unit)? = null) = initNode(styleClass, VBox(), init) fun hbox(styleClass: String? = null, init: (HBox.() -> Unit)? = null) = initNode(styleClass, HBox(), init) fun <T : Node> initNode(styleClass: String? = null, tag: T, init: (T.() -> Unit)? = null): T { init?.invoke(tag) tag.styleClass.add(styleClass) return tag } 

NOTA: He investigado la biblioteca de TornadoFX, pero me gusta encontrar una solución propia debido principalmente al propósito de aprendizaje.

Finalmente he llegado a la solución usando el consejo de @ zsmb13.

Aquí está para reference de otros

 fun <T : Pane> T.children(init: (Children.() -> Unit)? = null): Children { val ch = Children() ch.parent = this init?.invoke(ch) return ch } class Children : Layout() { var parent: Pane? = null override fun <T : Node> initNode(styleClass: String?, tag: T, init: (T.() -> Unit)?): T { val node: T = super.initNode(styleClass, tag, init) parent?.children?.add(node) return node } } open class Layout { var pane: Pane? = null open fun <T : Node> initNode(styleClass: String? = null, tag: T, init: (T.() -> Unit)? = null): T { init?.invoke(tag) tag.styleClass.add(styleClass) return tag } fun region(styleClass: String? = null, init: (Region.() -> Unit)? = null) = initNode(styleClass, Region(), init) fun vbox(styleClass: String? = null, init: (VBox.() -> Unit)? = null) = initNode(styleClass, VBox(), init) fun hbox(styleClass: String? = null, init: (HBox.() -> Unit)? = null) = initNode(styleClass, HBox(), init) fun label(styleClass: String? = null, init: (Label.() -> Unit)? = null) = initNode(styleClass, Label(), init) fun button(styleClass: String? = null, init: (Button.() -> Unit)? = null) = initNode(styleClass, Button(), init) fun progressBar(styleClass: String? = null, init: (ProgressBar.() -> Unit)? = null) = initNode(styleClass, ProgressBar(), init) } fun <T : Pane> layout(styleSheet: String = "", init: Layout.() -> T): T { val layout = Layout() val pane = layout.init() layout.pane = pane pane.stylesheets.add(layout.javaClass.classLoader.getResource(styleSheet).toExternalForm()) return pane } 

Y el uso es como a continuación:

 private var loadProgress: ProgressBar? = null private var progressText: Label? = null val layout = layout("xyz.css") { vbox("screen") { prefWidth = 500 prefHeight = 450 children { region { minHeight = 250.0 } hbox { children { region { minWidth = 30.0 } label("large-label") { text = "Foo" } label("large-label") { text = "Bar" } region { minWidth = 20.0 } label("small-label") { text = "xyz" } } } region { minHeight = 10.0 } loadProgress = progressBar("progress") { minWidth = this@vbox.prefWidth } hbox { children { region { minWidth = 30.0 } progressText = label("progress-label") } } } } } 
  • ¿Puedo aplicar la function infija dentro de la propia class sin `this`?
  • Quiero mostrar DialogFragment en Android usando Kotlin
  • ¿Cómo correctamente serializar tal JSON por medio de GSON Android?
  • Kotlin Date.daysDespués de la function diferente valor de retorno con los mismos arguments
  • Revertir códigos de Kotlin a Java en Android Studio Canary 5
  • ¿Cómo ejecutar código Kotlin en un plugin IntelliJ?
  • Duplicación del adaptador en la Vista de reciclador
  • ¿Cómo instalar y configurar Kara Web Framework?
  • Ejecuta una class de kotlin con la function principal en el estudio Android
  • Comportamiento inesperado con AWS Lambda
  • Problema de compilation Dagger2 en kotlin