TornadoFx 頁面之間的資料傳遞

2023-07-01 15:00:41

原文地址: TornadoFx 頁面之間的資料傳遞 - Stars-One的雜貨小窩

和Android開發一樣,經常遇到兩個頁面之間需要進行資料的互動傳輸,本文講解下TornadoFx框架中,頁面之間的資料傳遞步驟方法

方法1 - 使用構造方法

首先,我們知道TornadoFx中,頁面可以是View或Fragment,然後View或Fragment物件中提供了對應的開啟視窗的方法

比如說

  • openModal
  • openWindow
  • openInternalWindow

3種方法就是視窗模式有些不同,具體說明可以參考此檔案3. Components

而我們需要傳遞資料,最簡單的一種方法就是通過構造方法去傳,如下面例子

class TestParamView : View("My View") {
    override val root = vbox {
        setPrefSize(300.0,300.0)

        button("跳轉頁面") {
            action {
                TestParamAView(1).openModal()
            }
        }
    }
}


class TestParamAView(val type:Int) : View() {

    override val root = vbox {
        setPrefSize(300.0,300.0)
        text(type.toString())

    }
}

效果如下所示:

那麼,如果需要頁面結束回傳資料呢?

這裡,TornadoFx預設沒有相關方法,我們只能自己改造著實現了

既然我們可以傳參,那麼,我們也可以將函數回撥傳入,之後新頁面關閉之前回撥一下我們的方法即可實現上述要求

假設我們需要新頁面返回String型別的資料,具體程式碼如下:

class TestParamView : View("My View") {
    override val root = vbox {
        setPrefSize(300.0, 300.0)

        button("跳轉頁面") {
            action {
                val closeAction = { s: String ->
                    println("這是返回的資料: $s")
                }
                TestParamAView(1, closeAction).openModal()
            }
        }
    }
}


class TestParamAView(val type: Int, closeAction: (String) -> Unit) : View() {

    override val root = vbox {
        setPrefSize(300.0, 300.0)
        text(type.toString())

        button("返回資料") {
            action {
                closeAction.invoke("資料11")
                close()
            }
        }
    }
}

效果如下,可以看見控制檯也是已經輸出了返回的資料

上面流程,我們需要手動在呼叫close方法前才回撥closeAction,如果想要點選頁面右上角關閉而返回的話,應該怎麼做?

View和Fragment有對應的生命週期,在onUndock()方法來實現攔截即可

class TestParamView : View("My View") {
    override val root = vbox {
        setPrefSize(300.0, 300.0)

        button("跳轉頁面") {
            action {
                val closeAction = { s: String ->
                    println("這是返回的資料: $s")
                }
                TestParamAView(1, closeAction).openModal()
            }
        }
    }
}


class TestParamAView(val type: Int, closeAction: (String) -> Unit) : View() {

    override val root = vbox {
        setPrefSize(300.0, 300.0)
        text(type.toString())

        button("返回資料") {
            action {
                close()
            }
        }
    }
    
    override fun onUndock() {
        super.onUndock()
        closeAction.invoke("資料11")
    }
}

之後不管是通過程式碼觸發close方法還是點選頁面右上角,最終都會走到onUndock方法裡去

然後剩下的就是邏輯完善了,比如在什麼時機傳回資料,傳回其他型別的資料,各位參考上面思路即可

方法2 - 使用param()方法

如果說你的使用情景中,開啟的View或Fragment都是固定的一個物件,可以使用TornadoFx框架提供的find方法來開啟頁面

find方法裡同時提供了傳參使用,如下面例子:

class TestParamView : View("My View") {
    override val root = vbox {
        setPrefSize(300.0, 300.0)

        button("跳轉頁面") {
            action {
                val closeAction = { s: String ->
                    println("這是返回的資料: $s")
                }
                find<TestParamAView>(
                    mapOf(
                        TestParamAView::type to 1,
                        TestParamAView::closeAction to closeAction

                    )
                ).openModal()
            }
        }
    }
}


class TestParamAView() : View() {
    val type: Int by param()
    val closeAction: (String) -> Unit by param()

    override val root = vbox {
        setPrefSize(300.0, 300.0)
        text(type.toString())

        button("返回資料") {
            action {
                close()
            }
        }
    }

    override fun onUndock() {
        super.onUndock()
        closeAction.invoke("資料11")
    }

}

傳承需要傳遞有個map集合,TestParamAView::type是反射的用法,實際上就是得到結果就是一個字串type,直接定義為"type"也是可行的,因為要相同的key才能注入引數,用反射的用法可以避免寫錯導致的不匹配問題

而在需要接受引數頁面內,通過param的委託方法來獲取資料

如果說你的情景可能引數會傳空,可以定義型別為空型別

 val type: Int? by param()

之後的返回引數和上面章節一樣,不再贅述