從命令式 Swing 轉向宣告式 JavaFX Script,最大差異在於「描述 UI 長什麼樣」而非「寫代碼怎麼構建 UI」。作者以 SwingWorker 教學中的 Flickr 圖片搜尋應用為藍本,逐步移植並對比兩種佈局哲學。
JFrame 主視窗JLabel + JTextFieldJLabel + JProgressBar(匹配/選取)JScrollPane + JList(自訂 CellRenderer)JLabelNetBeans Matisse 產生的 GroupLayout 代碼冗長難讀,雖工具支援好但手寫維護痛苦。

Box 控制垂直堆疊,FlowPanel 水平排列標籤與輸入框。缺點:進度條寬度須硬編碼,無法自動填滿容器右側,對齊靠肉眼調整。
Frame {
title: "JFX Image Search"
content: Box {
orientation: VERTICAL
border: EmptyBorder { top:10 left:10 right:10 bottom:10 }
content: [
FlowPanel { alignment: LEADING content: [ SimpleLabel{text:"Search"}, TextField{preferredSize:{width:425}} ] },
FlowPanel { alignment: LEADING content: [ SimpleLabel{text:"Matched Images"}, ProgressBar{preferredSize:{width:378}} ] },
ListBox { preferredSize:{height:200} },
FlowPanel { alignment: LEADING content: [ SimpleLabel{text:"Selected Image"}, ProgressBar{preferredSize:{width:382}} ] },
Label { opaque:true preferredSize:{height:250} border: LineBorder {} }
]
}
visible: true
}

GroupPanel 封裝 Swing GroupLayout,以行/列定義網格,支援 resizable 自動分配剩餘空間,組件間距自動處理平台差異。
Frame {
title: "JavaFX Image Search"
content: GroupPanel {
var searchRow = Row {}
var matchedRow = Row {}
var thumbRow = Row { resizable: true }
var selectedRow = Row {}
var imageRow = Row { resizable: true }
var mainCol = Column { resizable: true }
rows: [searchRow, matchedRow, thumbRow, selectedRow, imageRow]
columns: mainCol
content: [
// 搜尋列:巢狀 GroupPanel 切分 Label/欄位兩欄
GroupPanel {
autoCreateContainerGaps: false
row: searchRow column: mainCol
var row = Row {}
var labelCol = Column {}
var fieldCol = Column { resizable: true }
rows: row columns: [labelCol, fieldCol]
content: [
SimpleLabel { text:"Search:" row:row column:labelCol },
TextField { row:row column:fieldCol columns:50 }
]
},
// 進度列:同理切分 Label/ProgressBar
GroupPanel { ... row: matchedRow ... content: [ SimpleLabel{...}, ProgressBar{} ] },
// 縮圖列表:單組件直接指定 row/column
ListBox { preferredSize:{height:200,width:400} row:thumbRow column:mainCol },
// 選取進度列
GroupPanel { ... row: selectedRow ... },
// 大圖顯示
Label { opaque:true preferredSize:{height:300,width:400} row:imageRow column:mainCol border:LineBorder{} }
]
}
visible: true
}

預先宣告 var searchRow = Row {},供外層與內層 GroupPanel 共享引用,實現跨層級對齊。
巢狀面板設 false 避免雙重邊距,保持緊湊。
縮圖列與大圖區設 resizable: true,視窗縮放時自動分配多餘空間。
NetBeans 插件與 JavaFXPad 均提供上下文感知補全,屬性、組件一鍵插入,大幅降低學習門檻。

宣告式語法配合 GroupPanel,以極少代碼實現專業級響應式佈局。無視覺設計器亦非障礙——即時預覽 + 智能補全讓手寫 UI 成為享受。下一步將串接真實 Flickr API,完成完整應用遷移。