JSpinner工作起来好像是在JList或者JComboBox中间放了一个JFormattedTextField在JList或者JComboBox中用户可以提前设定好要输入的值JSpinner也提供这样的一种机制这个控件的另一个部分是JFormattedTextField如何显示和输入不由那些小的控制格控制比如JList相反可以通过JFormattedTextField来输入或通过边上的两个小箭头来浏览不同的可用的值 图示显示了Spinner伴随不同的输入类型是什么样子图示的顶端的JSpinner是一个用来显示法语星期通过SpinnerListModel中间的是一个通过SpinnerDateModel显示日期的JSpinner底部的是使用SpinnerNumberModel的JSpinner每一个都是通过各自神秘的方式在本文的后面我们将要学习 图示JSpinner实例 要创建和操纵JSpinner许多类都将被调用最重要的是JSpinner自己最重要的两个准素集包括SpinnerModel接口包括可选择的集合中的选项还有JSpinnerDefaultEditor的实现用来捕获所有选择庆幸的是许多其它调用的类都是在后台工作的比如一旦你给SpinnerNumberModel提供了数字的范围并且用这个类来协助Spinner你的工作实际上是完成了 创建JSpinner控件 JSpinner类包括两个构造函数来初始化控件 public JSpinner() JSpinner spinner = new JSpinner(); public JSpinner(SpinnerModel model) SpinnerModel model = new SpinnerListModel(args); JSpinner spinner = new JSpinner(model); 开始的时候可以没有数据模型后面可以使用它来跟蹤JSpinner的方法另一个方法在创建这个控件的时候使用完整的模型实现SpinnerModel接口它里面有三个具体的子类可以使用SpinnerDateModelSpinnerListModel和SpinnerNumberModel伴随着他们的抽象父类AbstractSpinnerModel如果不指名模型那么SpinnerNumberModel将默认使用而显示和编辑的控件是JFormattedTextField编辑的基本功能是通过一系列JSpinner的内部类实现的DateEditorListEditor和NumberFormat还有父类中DefaultEditor的支持 JSpinner属性 除了创建JSpinner对象之外你还可以通过表一中的九个属性中的一个来进行配置 Table JSpinner 属性value属性中的值允许你更改当前控件的设置nextValue和perviousValue可以使你以不同的方向察看模型中的入口 使用ChangeListener来监听JSpinner events JSpinner直接支持一种事件监听changeListener在别的地方当commitEdit()方法被调用这个事件将被触发告诉你spinner的值发生改变为了证明列表联系到一个自定义的ChangeListener与图示的程序相关联 列表 JSpinner with ChangeListener import javaawt*; import javaxswing*; import javaxswingevent*; import javatext*; import javautil*; public class SpinnerSample { public static void main (String args[]) { Runnable runner = new Runnable() { public void run() { JFrame frame = new JFrame(JSpinner Sample); framesetDefaultCloseOperation(JFrameEXIT_ON_CLOSE); DateFormatSymbols symbols = new DateFormatSymbols(LocaleFRENCH); ChangeListener listener = new ChangeListener() { public void stateChanged(ChangeEvent e) { Systemoutprintln(Source: + egetSource()); } }; String days[] = symbolsgetWeekdays(); SpinnerModel model = new SpinnerListModel(days); JSpinner spinner = new JSpinner(model); spinneraddChangeListener(listener); JLabel label = new JLabel(French Days/List); JPanel panel = new JPanel(new BorderLayout()); paneladd(label BorderLayoutWEST); paneladd(spinner BorderLayoutCENTER); frameadd(panel BorderLayoutNORTH); SpinnerModel model = new SpinnerDateModel(); JSpinner spinner = new JSpinner(model); spinneraddChangeListener(listener); JLabel label = new JLabel(Dates/Date); JPanel panel = new JPanel(new BorderLayout()); paneladd(label BorderLayoutWEST); paneladd(spinner BorderLayoutCENTER); frameadd(panel BorderLayoutCENTER); SpinnerModel model = new SpinnerNumberModel(); JSpinner spinner = new JSpinner(model); spinneraddChangeListener(listener); JLabel label = new JLabel(Numbers); JPanel panel = new JPanel(new BorderLayout()); paneladd(label BorderLayoutWEST); paneladd(spinner BorderLayoutCENTER); frameadd(panel BorderLayoutSOUTH); framesetSize( ); framesetVisible (true); } }; EventQueueinvokeLater(runner); } 运行这个程序可以示范listener的用法(当然你也会发现更多关于ChangeListener的有意义的方法) 定制JSpinner的外观 同所有的Swing控件JSpinner在不同的系统定义lookandfeel类型下拥有不同的外观如示图这个控件期初看起来像一个textfield不同点是绘制了两个箭头 示图 JSpinner under different lookandfeel types 集合中的个UIResource属性在表格中列举有限的方法绘制text field和箭头 Table JSpinner UIResource 元素 SpinnerModel 接口 到目前我们已经看到了如何同一个主JSpinner类连接SpinnerModel接口是控件的数据模型SpinnerModel的定义如下 public interface SpinnerModel { // Properties public Object getValue(); public void setValue(Object); public Object getNextValue(); public Object getPreviousValue(); // Listeners public void addChangeListener(ChangeListener); public void removeChangeListener(ChangeListener); } SpinnerModel中的六个方法直接绘制了JSpinner而JSpinner的方法间接调用模块中的方法在监听的状况下事件将联系到监听器 AbstractSpinnerModel类 AbstractSpinnerModel类基本要实现的是SpinnerModel接口它提供了管理和通知的监听列表子类必须实现接口中的四个方法SpinnerModel中的三个具体实现如下SpinnerDateModelSpinnerListModel和SpinnerNumberModel SpinnerDateModel类 从名字可以推断出SpinnerDateModel提供了数据的选择这个类有两个构造函数一个默认选择所有的数据另一个要求你给出范围 public SpinnerDateModel()SpinnerModel model = new SpinnerDateModel();JSpinner spinner = new JSpinner(model);public SpinnerDateModel(Date value Comparable start Comparable end int calendarField)Calendar cal = CalendargetInstance();Date now = calgetTime();caladd(CalendarYEAR );Date startDate = calgetTime();caladd(CalendarYEAR );Date endDate = calgetTime();SpinnerModel model = new SpinnerDateModel(now startDate endDate CalendarYEAR);JSpinner spinner = new JSpinner(model); 如果不指名任何参数就没有开始和结束点下面的例子展示了使用参数来表示年的范围最后一个成员变量应该是Calendar类中的一个定值 ·CalendarAM_PM ·CalendarDAY_OF_MONTH ·CalendarDAY_OF_WEEK ·CalendarDAY_OF_WEEK_IN_MONTH ·CalendarDAY_OF_YEAR ·CalendarERA ·CalendarHOUR ·CalendarHOUR_OF_DAY ·CalendarMILLISECOND ·CalendarMINUTE ·CalendarMONTH ·CalendarSECOND ·CalendarWEEK_OF_MONTH ·CalendarWEEK_OF_YEAR ·CalendarYEAR 注意SpinnerDateModel不包含任何Calendar类中的时间域所以不能通过SpinnerDateModel在JSpinner中翻转 表格列出了SpinnerModel中的三个属性四个关于SpinnerDateModel Table SpinnerDateModel 属性典型地唯一的新属性中你将要用来获得最终的日期尽管所有的结果都被包裹在getValue()中以适当的数据类型如果在构造函数中提供了数据的表示范围那么previous和next的值将是null在边界条件下 SpinnerListModel SpinnerListModel提供了从一个入口列表中选择或者至少是字符串表述这个类有三个构造函数 public SpinnerListModel()SpinnerModel model = new SpinnerListModel(); JSpinner spinner = new JSpinner(model); public SpinnerListModel(List<?> values)List<String> list = args; SpinnerModel model = new SpinnerListModel(list); JSpinner spinner = new JSpinner(model); public SpinnerListModel(Object[] values)SpinnerModel model = new SpinnerListModel(args); JSpinner spinner = new JSpinner(model); 当没有参数提供时这个模型包括一个元素字符串emptyList版保留一个对list的引用而不是list的拷贝如果改变了list那么模型中的list也将改变数组版本的创建了一个私有的内部类并且实例化一个list对于list和数组版本初始选择的是第一个元素否则将抛出一个IllegalArgumentException异常 如表格显示属性中增添的是set和get list Table SpinnerListModel 属性educitycn/img_///gif > SpinnerNumberModel类 SpinnerNumberModel提供了从一个开区间或闭区间选择数字的模式数字可以使Number类的所有子类包括Integer和Double他有四个构造函数 public SpinnerNumberModel()SpinnerModel model = new SpinnerNumberModel(); JSpinner spinner = new JSpinner(model); public SpinnerNumberModel(double value double minimum double maximum double stepSize)SpinnerModel model = new SpinnerNumberModel( ); JSpinner spinner = new JSpinner(model); public SpinnerNumberModel(int value int minimum int maximum int stepSize)SpinnerModel model = new SpinnerNumberModel( ); JSpinner spinner = new JSpinner(model); public SpinnerNumberModel(Number value Comparable minimum Comparable maximum Number stepSize)Number value = new Integer(); Number min = new Integer();Number max = new Integer(); Number step = new Integer();SpinnerModel model = new SpinnerNumberModel(value min max step); JSpinner spinner = new JSpinner(model); 如果最大或最小值为null则为开区间对于没有参数的初始值为步进为步进是整形的如果你设为那么将不会完成 表格展示了SpinnerNumberModel的属性 Table SpinnerNumberModel 属性educitycn/img_///gif > 自定义模型 一般来说可用的JSpinner模型已经足够了所以没有必要创建他的子类了但是并不是所有场合都能满足比如你可能希望使用一个包装了SpinnerListModel的模型代替停止在第一个或最后一个元素他包装了另一个结束在列表中给出了具体实现 Listing RolloverSpinnerListModel 类 import javaxswing*; import javautil*; public class RolloverSpinnerListModel extends SpinnerListModel { public RolloverSpinnerListModel(List values) { super(values); } public RolloverSpinnerListModel(Object[] values) { super(values); } public Object getNextValue() { Object returnValue = supergetNextValue(); if (returnValue == null) { returnValue = getList()get(); } return returnValue; } public Object getPreviousValue() { Object returnValue = supergetPreviousValue(); if (returnValue == null) { List list = getList(); returnValue = listget(listsize() ); } return returnValue; }} JSpinner编辑器 对于JSpinner每个可用的模型一个次要的支持类JSpinner的一个内部类然而这个模块可以控制控件是否可选JSpinner编辑器允许你控制如何显示和编辑每个可选的值 JSpinnerDefaultEditor类 JSpinner的setEditor()方法允许你将任何Jcomponent作为JSpinner的编辑器当然你可以那样做更典型的是你将用JSpinnerDefaultEditor的子类作运行以JformattedTextField作为简单的编辑器工作将提供所有你需要的基本功能它包括一个基本的构造函数 public JSpinnerDefaultEditor(JSpinner spinner)JSpinner spinner = new JSpinner(); JComponent editor = JSpinnerDefaultEditor(spinner); spinnersetEditor(editor); 在表格中可以看到有两个属性 Table JSpinnerDefaultEditor propertieseducitycn/img_///gif > 在不知道使用的是哪个模型工作的情况下在这个级别的你可以做的是改变JformattedTextField中的文字显示更典型的是你将改变模型编辑器的某些自定义方面 JSpinnerDateEditor类 DateEditor允许你定制不同的日期显示方式使用javatext包中SimpleDateFormat类察看Javadoc了解更多的关于SimpleDateFormat的可用格式模式如果你不喜欢默认的地显示方式可以通过给构造函数的第二个参数传递一个新参数来改变显示模式 public JSpinnerDateEditor(JSpinner spinner)SpinnerModel model = new SpinnerDateModel(); JSpinner spinner = new JSpinner(model);JComponent editor = JSpinnerDateEditor(spinner); spinnersetEditor(editor); public JSpinnerDateEditor(JSpinner spinner String dateFormatPattern)SpinnerModel model = new SpinnerDateModel(); JSpinner spinner = new JSpinner(model); JComponent editor = JSpinnerDateEditor(spinner MMMM yyyy); spinnersetEditor(editor); 默认情况格式是M/d/yy h:mm a或者// : PM 代表年的圣诞节的某个时间后面的例子将要显示 December 编辑器的两个属性在表格中 Table JSpinnerDateEditor属性educitycn/img_///gif > JSpinnerListEditor类 当使用SpinnerListModel类工作时ListEditor不支持任何特殊格式而是提供了前置类型支持既然模块的所有入口都知道了编辑器将尝试匹配用户输入的字符这里只有一个构造函数但是你可能几乎用不到 public JSpinnerListEditor(JSpinner spinner) 在表格中将看到ListEditor只有一个属性 educitycn/img_///gif >JSpinnerNumberEditor类 NumberEditor和DateEditor的工作方式很相似允许你输入定制的显示模式代替SimpleDateFormat工作NumberEditor可以协助javatext包中的DecimalFormat类就像DateEditor一样他又两个构造函数 public JSpinnerNumberEditor(JSpinner spinner)SpinnerModel model = new SpinnerNumberModel( );JSpinner spinner = new JSpinner(model);JComponent editor = JSpinnerNumberEditor(spinner);spinnersetEditor(editor);public JSpinnerNumberEditor(JSpinner spinner String decimalFormatPattern)SpinnerModel model = new SpinnerNumberModel( );JSpinner spinner = new JSpinner(model);JComponent editor = JSpinnerNumberEditor(spinner ######);spinnersetEditor(editor); 第二个构造函数使用默认的字符串格式如果数字太大将使用逗号如果结果是一个完整的数将不会用十进制显示 表格中显示editor的两个属性 Table JSpinnerNumberEditor 属性educitycn/img_///gif > 总结 在这篇文章中你学习到了Swing中的JSpinner控件当你要控制某些选择在一定的范围中时JSpinner可以让你通过翻滚来选择需要的值你学习到了如何提供这些要选择的值通过使用SpinnerDateModel和DateEditorSpinnerListModel和ListEditorSpinnerNumberModel和NumberEditor来设置日期 |