Understanding Swing’s Model
经常用Swing 开发Java GUI 程序的人一定听过这样的说法,Swing 控件是按MVC结构设计的。更准确地说,Swing是Model-driven的结构。但不同Swing控件的Model,其作用是否相同呢?比如当你在使用JButton时,你很少需要关心ButtonModel的存在,但在JTable使用时,你却总是需要用到 TableModel。更进一步,当你频繁的使用JTable时,你会发现你可能不仅用到了TableModel,还用到TableColumnModel, ListSelectionModel。这使我们意识到,Model存在不同的种类,不同类型的Model实现不同的功能。
GUI-State Model
首先,我们讨论第一种Model, GUI–State Model。GUI-State Model的作用在于标识控件的视觉状态 (visual status)。例如按钮是否被点击,列表中的Item是否被选中。Swing的控件会代理对GUI-State Model的操作,通常我们不要直接操作GUI–State Model。
ButtonModel
最常见的GUI-State Model是ButtonModel,属于这个范畴的控件有JButton ,JToggleButton ,JCheckBox, JRadioButton, JMenu, JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem。(所有AbstractButton的子类)
ButtonModel需要标识的状态有:
- PRESSED: Button是否被点击了
- ENABLED: Button能否被点击(是否显示呈灰色)
- ROLLOVER: 鼠标是否从Button上划过。Button通过判断这个属性判断是否要显示RolloverIcon,当然前提是Button通过setRolloverIcon,设置了RolloverIcon
- SELECTED: 只对RadioButton or Checkbox 有用
- ARMED: 鼠标点击Button后,是否在Button该释放
显而易见,这些属性都只和显示有关。对于GUI-State Model,只有以下两种情况我们需要关心它的处在 :(1)我们想改变控件缺省的视觉行为(假定这种情况很少发生) (2)出于某种显示目的共用Model,操作一个控件会改变另外一个控件的状态(下面会讨论到这种情况),其他情况下我们可以忽视它。当然还有一种情况我们需要注意,这就是在使用JRadioButton时。因为使用JRadioButton时,一组JRadioButton同时只能有一个被选中(SELECTED),这当然只有通过操作ButtonModel的SELECTED属性来实现。不过,Swing针对这个问题引入了ButtonGroup类,通过ButtonGroup.add()方法设置同一个 button group,因此我们同样不需要直接操作ButtonModel。
BoundedRangeModel
另一个常见的GUI-State Model是BoundedRangeModel,属于这个范畴的控件有JProgressBar JScrollBar JSlider。
BoundedRangeModel标识的主要状态有:min,max,value(int),同样的,我们很少直接操作BoundedRangeModel。使用JProgressBar 最常见的方式是在构造函数里指定min,max或是通过get/set读写min,max,value。而控件再把这些请求转发给BoundedRangeModel。
前面提到出于某种显示目的,我们有可能需要直接操作GUI-State Model。以下是一种可能的情况(scenario):当我们把一幅面积较大的图像放在JScrollPane,同时希望通过移动滑杆(JSlider)来控制显示图像显示在JScrollPane的部分。常见的做法是监听BoundedRangeModel的ChangeEvent事件(addChangeListener(ChangeListener l)),当JSlider改变了Model的值时在ChangeListener对显示作相应的调整。
TableColumnModel
TableColumnModel是JTable特有的GUI-State Model。TableColumnModel用于管理TableColumn。而TableColumn代表了JTable中的每一列数据的视觉属性,比如该列对应的data-model index(这决定了要显示的内容,参见后面叙述),该列的宽度是否可变,列的最大、最小、首选宽度;该列的绘制器TableCellRenderer和编辑器TableCellEditor(JTable是面向列的,它基于每一列进行绘制和编辑)