當顯示區(qū)域受限時,滾動窗格,即JScrollPane,就有了用武之地,用來顯示尺寸較大或者尺寸可以的動態(tài)變化的控件。
透過滾動窗格看東西,就像隔窗看花,只能看到一尺見方的天地,想要看到更多,就得左右移動,改變角度。
滾動窗格是Decorator模式的實例,能夠動態(tài)地給控件添加滾動特性。一個典型的例子就是文本區(qū)(JTextArea)沒有滾動條,如果需要的話,可以將文本區(qū)插入到滾動窗格。
原理

如圖,滾動窗格由觀察窗口(JViewport)和水平、垂直的滾動條(JScrollBar)等構成。JViewport給數據源提供了一個觀察的窗口,數據源可以是JTextArea,也可以是其他類型的控件。當數據源的內容超出了JViewport顯示范圍時,滾動條會自動出現。
JViewport可視區(qū)域的大小由兩方面因素決定。一是,若數據源實現了Scrollable接口,則可視區(qū)域的大小依據getPreferredScrollableViewportSize()方法的返回值。二是,若數據源是普通的控件,則可視區(qū)域的大小依據getPreferredSize()方法的返回值。需要注意的是,后者因為JViewport的默認大小足以顯示數據源的所有內容,所以不會出現滾動條。
滾動條允許用戶調整可視區(qū)域顯示的內容。下圖描述了滾動條的三個部分:滾動條(knob),按鈕(button),以及空白區(qū)(track):

當用戶左右移動滾動條時,可視區(qū)域相應地左右變化;當用戶單擊按鈕時,可視區(qū)域滾動一個單位距離;當用戶點擊空白區(qū)時,可視區(qū)域滾動一個距離塊。一個單位距離具體有多少,或參考getScrollableUnitIncrement()方法,或由JScrollPane.getHorizontalScrollBar().setUnitIncrement()方法設定。除此之外,用戶還可以設置滾動條的顯示方式。
示例
下面用一個具體的例子演示滾動窗格的用法:
JPanel container = new JPanel();
DesignGridLayout layout = new DesignGridLayout(container);
JScrollPane jScrollPane = new JScrollPane(new JButton("B"));
layout.row().grid().add(new JButton("A")).add(jScrollPane);
layout.row().grid().add(new JButton("C")).spanRow();
jFrame.add(container);
第三方布局管理器——DesignGridLayout派生于Canonical Grids理念,致力于構建平衡、漂亮的UI。默認情況下,DesignGridLayout不允許非滾動的JButton控件擴展到下一行,只能以PreferredSize(下圖BUTTON A大小)顯示。在這種情況下,new JScrollPane(new JButton("B"))語句就像是游戲中的技能包,賦予JButton新的滾動特性,從而滿足了DesignGridLayout的擴展要求,成功讓BUTTON B占據兩行。效果圖如下:

總結
本文討論了滾動窗格,分析了它的原理,并用一個詳細的示例演示了滾動窗格的用法。