当显示区域受限时,滚动窗格,即JScrollPane,就有了用武之地,用来显示尺寸较大或者尺寸可以的动态变化的控件。
透过滚动窗格看东西,就像隔窗看花,只能看到一尺见方的天地,想要看到更多,就得左右移动,改变角度。
滚动窗格是Decorator模式的实例,能够动态地给控件添加滚动特性。一个典型的例子就是文本区(JTextArea)没有滚动条,如果需要的话,可以将文本区插入到滚动窗格。
原理
如图,滚动窗格由观察窗口(JViewport)和水平、垂直的滚动条(JScrollBar)等构成。JViewport给数据源提供了一个观察的窗口,数据源可以是JTextArea,也可以是其他类型的控件。当数据源的内容超出了JViewport显示范围时,滚动条会自动出现。
JViewport可视区域的大小由两方面因素决定。一是,若数据源实现了Scrollable接口,则可视区域的大小依据getPreferredScrollableViewportSize()
方法的返回值。二是,若数据源是普通的控件,则可视区域的大小依据getPreferredSize()
方法的返回值。需要注意的是,后者因为JViewport的默认大小足以显示数据源的所有内容,所以不会出现滚动条。
滚动条允许用户调整可视区域显示的内容。下图描述了滚动条的三个部分:滚动条(knob),按钮(button),以及空白区(track):
当用户左右移动滚动条时,可视区域相应地左右变化;当用户单击按钮时,可视区域滚动一个单位距离;当用户点击空白区时,可视区域滚动一个距离块。一个单位距离具体有多少,或参考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占据两行。效果图如下:
总结
本文讨论了滚动窗格,分析了它的原理,并用一个详细的示例演示了滚动窗格的用法。