在 TornadoFX 中使用工作区时如何使用范围?

How to work with Scopes when using Workspaces in TornadoFX?

我正在使用 TornadoFX 的 Workspace 功能,我正试图让它们与 Scopes 一起工作。当我启动应用程序时,我需要设置一些东西,完成后我启动 TornadoFX 应用程序,并为我的第一个视图提供 Scope。在那之后,我希望能够 dock 在新的 Scope 中对我的 Workspace 进行其他视图,但是由于某些原因这不起作用:原来的 View 没有取消停靠,但新的 View 停靠了,我只是在屏幕上看不到它。可能是什么问题呢?这是我重现问题的代码:

fun main(args: Array<String>) {
    Application.launch(TestApp::class.java, *args)
}


class ParentScope : Scope() {
    val id = UUID.randomUUID().toString().substring(0, 4)
}

class ChildScope : Scope() {
    val id = UUID.randomUUID().toString().substring(0, 4)
}

class TestApp : App(Workspace::class) {

    override fun onBeforeShow(view: UIComponent) {
        workspace.dock<ParentView>(ParentScope())
    }
}

class ParentView : View("parent") {

    override val scope = super.scope as ParentScope

    override val root = hbox {
        button("new child") {
            action {
                workspace.dock<ChildView>(ChildScope())
            }
        }
    }

    override fun onDock() {
        logger.info("Docking parent (${scope.id})")
    }

    override fun onUndock() {
        logger.info("Undocking parent (${scope.id})")
    }

}

class ChildView : View("child") {

    override val scope = super.scope as ChildScope

    override val root = hbox {
        text("In child")
    }

    override fun onDock() {
        logger.info("Docking child (${scope.id})")
    }

    override fun onUndock() {
        logger.info("Undocking child (${scope.id})")
    }

}

点击new child按钮后的输出是这样的:

10:56:19.415 [JavaFX Application Thread] INFO  Test - Docking parent (d202) 
10:56:23.967 [JavaFX Application Thread] INFO  Test - Docking child (cbc5)

我看到的是一样的ParentView。如果我再次单击 new childChildView 将取消停靠,新的 ChildView 将停靠,但我仍然只看到 ParentView:

10:56:31.228 [JavaFX Application Thread] INFO  Test - Undocking child (cbc5)
10:56:31.228 [JavaFX Application Thread] INFO  Test - Docking child (1dd8)

App 已经定义了一个 Scope 和对应的 Workspace 实例,因此当您的初始 View 停靠在 Workspace 中时,您的新ParentScope 定义了一个新的 Workspace 实例。当您将 ChildView 停靠到那个 Workspace 时,它确实会这样做,但有问题的工作区不会显示在屏幕上。

要解决此问题,您可以像这样覆盖应用程序的主要范围:

class TestApp : WorkspaceApp(ParentView::class) {
    init {
        scope = ParentScope()
    }
}

另请注意,我使用 WorkspaceApp 子类,因此我不需要手动停靠 ParentView

在查看此问题时,我意识到如果您将 UIComponent 停靠到工作区中,它应该假定它已停靠在工作区中。因此,我已经提交了一个修复程序,以便您的初始代码可以正常工作没有修改。