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") } } } } } 
  • AutoValue con GsonTypeAdapter en Kotlin
  • No se puede establecer el tipo de contenido en la request SOAP
  • ¿Cómo permitir que una class de datos implemente Interfaz / extiende properties de Superclass en Kotlin?
  • ¿El DAO de Kotlin debería ser opcional o nulo?
  • La secuencia de commands de Kotlin no puede acceder a los resources de META-INF (persistence.xml) desde el file jar
  • ¿Cómo compartir los mismos constructores en diferentes classs también conocidas como definir constructores en una interfaz?
  • ¿Cómo puedo get una reference a un object Kotlin por su nombre?
  • cómo integrar kotlin con node.js
  • volver a habilitar la conversión de intellij java a kotlin
  • La inferencia de tipo del comstackdor Kotlin no puede elegir qué método llamar (ambigüedad con types generics)
  • Kotlin custom setter