You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TornadoFX中FlowPane如何实现类似ListCellFragment的模型绑定渲染?

Question

I'm working with TornadoFX and want to replicate the ListCellFragment functionality for a FlowPane—specifically, rendering each cell with multiple controls and SVG drawings, bound to a shapeItem model. Right now, my code uses a simple button:

class LibraryView : View("Current Library") {
    val shapeLibraryViewModel : LibraryViewModel by inject()
    override val root = anchorpane{
        flowpane {
            bindChildren(shapeLibraryViewModel.libraryItemsProperty){ shapeItem ->
                button(shapeItem.nameProperty)
            }
        }
    }
}

Since there's no pre-built component for FlowPane like ListCellFragment, I'm wondering if I need to create a similar custom component, or if there's a lighter-weight way to achieve this?

Answer

Great question! TornadoFX doesn't have a direct equivalent to ListCellFragment for FlowPane, but you don't need to build a full custom component from scratch—there are two lightweight approaches that work perfectly for this scenario.

Option 1: Reusable Fragment for Cells

If you want a cell layout you can reuse across multiple views, create a small Fragment that encapsulates your cell's UI and binds directly to the shapeItem model:

// Define the reusable cell fragment
class ShapeCellFragment(private val shapeItem: ShapeItem) : Fragment() {
    override val root = vbox(alignment = Pos.CENTER, spacing = 4.0, styleClass = arrayOf("shape-cell")) {
        // SVG drawing (replace with your actual SVG path logic)
        svgview("/assets/svg/${shapeItem.svgFileNameProperty.value}") {
            fitWidth = 60.0
            fitHeight = 60.0
        }
        // Label bound to the shape's name property
        label(shapeItem.nameProperty) {
            styleClass.add("shape-name")
        }
        // Action buttons tied to the shape item
        hbox(spacing = 4.0) {
            button("Edit") {
                action { /* Add your edit logic for this shapeItem */ }
            }
            button("Delete") {
                action { shapeLibraryViewModel.remove(shapeItem) }
            }
        }
    }
}

// Update your LibraryView to use the fragment
class LibraryView : View("Current Library") {
    val shapeLibraryViewModel : LibraryViewModel by inject()
    override val root = anchorpane{
        flowpane(spacing = 10.0, padding = Insets(10.0)) {
            bindChildren(shapeLibraryViewModel.libraryItemsProperty){ shapeItem ->
                add(ShapeCellFragment(shapeItem).root)
            }
        }
    }
}

Option 2: Inline Component Builder (Quick & Simple)

If you only need this cell layout once, you can build all the components directly inside the bindChildren lambda without a separate fragment:

class LibraryView : View("Current Library") {
    val shapeLibraryViewModel : LibraryViewModel by inject()
    override val root = anchorpane{
        flowpane(spacing = 10.0, padding = Insets(10.0)) {
            bindChildren(shapeLibraryViewModel.libraryItemsProperty){ shapeItem ->
                vbox(alignment = Pos.CENTER, spacing = 4.0, styleClass = arrayOf("shape-cell")) {
                    // SVG drawing
                    svgview("/assets/svg/${shapeItem.svgFileNameProperty.value}") {
                        fitWidth = 60.0
                        fitHeight = 60.0
                    }
                    // Bound name label
                    label(shapeItem.nameProperty)
                    // Action buttons
                    hbox(spacing = 4.0) {
                        button("Edit") { action { /* Edit logic here */ } }
                        button("Delete") { action { shapeLibraryViewModel.remove(shapeItem) } }
                    }
                }
            }
        }
    }
}

Key Takeaways

  • Both approaches let you bind directly to shapeItem observable properties, just like ListCellFragment does for lists.
  • Use the Fragment option for reusability, and the inline approach for one-off use cases to keep things concise.
  • Add CSS styles (like shape-cell or shape-name) to polish the appearance of your cells.

内容的提问来源于stack exchange,提问作者DanielMcQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:17:29