和Android開發一樣,經常遇到兩個頁面之間需要進行資料的互動傳輸,本文講解下TornadoFx框架中,頁面之間的資料傳遞步驟方法
首先,我們知道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
方法裡去
然後剩下的就是邏輯完善了,比如在什麼時機傳回資料,傳回其他型別的資料,各位參考上面思路即可
如果說你的使用情景中,開啟的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()
之後的返回引數和上面章節一樣,不再贅述