第九章 Swing用户界面组件

9.1 模型-视图-控制器设计模式
注意:在设计模式中,模型存储完整的内容,视图给出了内容的可视化显示(完整或者不完整)。一个更恰当的类比应当是摆好姿势给画家作画的模特(model)。此时,取决于画家是如何看模特的,并据此来作一张画。那张画师一副正规的肖像画,还是一幅印象派作品,还是一幅立体派作品(以古怪的曲线来描画四肢)完全取决于画家。
设计模式
模式首先说明使用环境,即产生设计问题的背景。接着解释问题,通常这里会有几个冲突的因素。最终,权衡这些冲突,给出问题的解决方案。
Swing按钮的模型-视图-控制器分析
对于大多数组件来说,模型类实现了名字结尾为Model的接口。
9.2 布局管理器概述
Java用一个非常出色的概念实现动态布局:容器内的所有组件都由一个布局管理器(layout manager)进行定位。在列举的示例中,所有的按钮都通过流布局管理器(flow layout manager)进行管理,这是面板的默认布局管理器。
注意:通常情况下,可以让流布局管理器控制组件间的水平和垂直间距。然而,也可以使用其他版本的流布局管理器的构造器指定水平和垂直间距。
9.2.1 边界布局
边界布局管理器(border layout manager)是每个JFrame的内容窗格的默认布局管理器。流布局管理器完全控制每个组件的位置,编辑布局管理器则不同,它允许我们选择每个组件的放置位置。可以选择把组件放置在内容窗格的中部、北部、南部、东部或者西部。
9.2.2 面板
注意:面板边界对用户来说是不可见的。面板只是用户界面设计者的一个组织机制。
9.2.3 网格布局
网格布局像电子数据表一样,按行列排列所有的组件。不过,它的每个单元大小都一样。
9.3 文本输入
9.3.1 文本域
提示:使用setColumns方法改变文本框的大小之后,需要调用包含这个文本框的容器的revalidate方法。
revalidate方法会重新计算容器内所有组件的大小,并且对它们重新进行布局。调用revalidate方法以后,布局管理器会重新设置容器的大小,然后就可以看到改变尺寸后的文本域了。
revalidate方法是JComponent类中的方法。它并不是马上就改变组件大小,而是编辑该组件需要改变大小。这样就避免了多个组件都要改变大小事带来的重复计算。但是,如果想重新计算一个JFrame中的所有组件,就需要调用validate方法——JFrame没有扩展JComponent。
9.3.2 标签与标签组件
标签是容纳文本的组件。
9.3.3 文本域变化跟踪
9.3.4 密码域
密码域是一种特殊的文本域。为了避免有某种企图的人看到密码,用户输入的字符不显示出来。每个输入的字符都用回显字符(echo character)表示,通常用星号“*”取代。Swing提供了JPasswordField类来实现这样的文本域。
9.3.5 格式化的输入域
1.整型输入
2.失去焦点的行为
提示:过滤器的另一个用途是把字符串中的所有字符变成大写。这样的过滤器很容易编写。在过滤器的insertString和replace方法中,把要被插入的字符串装换成大写,然后调用超类的方法。
3.过滤器
4.检验器
检验器必须扩展抽象类InputVerifier,并且定义verify方法。
5.其他标准的格式
DefaultFormatter可以格式化任何类的对象,只要该类有一个字符串类型参数的构造器和匹配的toString方法。
注意:在默认情况下,DefaultFormatter处于覆写(overwrite)状态。与其他格式器不同,也不很实用。可以调用setOverwriteMode(false)关闭覆写状态。
最后,MaskFormatter对包含一些常量和一些变量字符的固定大小的样式很有用。
表9-2 MaskFormatter符号
# 数字 A 字母或数字
? 字母 H 16进制数字[0-9A-Fa-f]
U 字母,转化为大写 * 任何字符
L 字母,转化为小写 ' 空格字符
注意,字符串是被掩码格式器格式化的,它和掩码具有完全相同的长度。如果用户在编辑过程中删除字符,那么它们将被占位符(holer character)替代。默认的占位符是空格,可以使用setPlaceholderCharacter方法改变它。
6.自定义格式器
9.3.6 文本区
提示:在Swing中,为组件增加滚动条的通用机制是将组件放置在滚动窗格中。
9.4 选择组件 2010-10-8 353页
9.4.1 复选框
9.4.2 单选按钮
9.4.3 边界
9.4.4 组合框
9.4.5 滑块
9.4.6 JSpinner组件
JSpinner是带有两个小按钮的文本域。当点击它时,可以增加或减少文本域的值。
在微调控制器(spinner)中的值可以是数字、日期、来自列表的值以及任何可以用上一个和下一个决定值的序列。JSpinner类为前三种情况定义了标准的数据模型,还可以自定义数据模型来描述任意的序列。
警告:在调用setValue方法设置新值之后,必须调用fireStateChanged方法,否则微调控制器不会更新。
警告:getNextValue和getPreviousValue方法不改变当前值。当用户点击微调控制器的向上箭头,将调用getNextValue方法。如果返回值不为null,调用setValue进行设置。
9.5 菜单
9.5.1 菜单创建
注意:在Windows和Macintosh程序中,菜单通常在外部资源文件中定义,使用资源标识符将其绑定到应用程序。当然编写程序也可以创建菜单,但通常并不这样做。在Java中,通常菜单在程序内部创建。这是因为Java处理外部资源的机制要比Windows和Mac操作系统具有更多的限制。
9.5.2 菜单项中的图标
9.5.3 复选框和单选按钮菜单项
9.5.4 弹出菜单
弹出菜单(pop-up menu)是一种不固定在菜单栏中随处浮动的菜单。
弹出菜单并不像常规菜单栏那样总是显示在框架的顶部,必须调用show方法菜单才能显示弹出菜单。调用时需要给出父组件以及相对父组件坐标的显示位置。
9.5.5 快捷键和加速器
在JDK1.4中,可以调用setDisplayedMnemonicIndex方法指定想加下划线的字符。
如果有一个Action对象,就可以把快捷键作为Action.MNEMONIC_KEY键值添加到对象中。如下所示:
cutAction.putValue(Action.MNEMONIC_KEY,new Integer('T'));
只能在菜单项的构造器中设定快捷键字母,而不是在菜单的构造器中。如果想为菜单设置快捷键,需要调用setMnemonic方法:
JMenu helpMenu=new JMenu("Help");
helpMenu.setMnemonic('H');
可以同时按下ALT键和菜单的快捷键在菜单栏中选择一个顶层菜单。
快捷键用来从当前打开的菜单中选择一个子菜单或者菜单项。而加速器是在打不开菜单的情况下选择菜单项的快捷键。例如,很多程序把加速器CTRL+O和CTRL+S关联到File菜单中的Open和Save菜单项。使用setAccelerator方法可以将加速器键关联到一个菜单项。这个方法使用KeyStroke类型的对象作为参数。例如,下面的调用将加速器CTRL+O关联到OpenItem菜单项。
openItem.setAccelerator(KeyStore.getKeyStroke(KeyEvent.VK_O,InputEvent.CTRL_MASK));
加速器只能关联到菜单项上,而不能关联到菜单上,加速器并不实际打开菜单。它只是直接激活菜单关联的动作事件。
注意在Windows下,ALT+F4用来关闭窗口。但这不是用Java程序设定的加速器。它是操作系统定义的快捷键。这个组合键永远触发活动窗口的WindowClosing事件,而不管该窗口的菜单是否有Close菜单项。
9.5.6 启用和禁用菜单项
警告:在现实菜单之前禁用菜单项是一种明智的选择,但是,对于同时拥有加速键的菜单项就不适用了。因为在加速键击键之前,菜单没有被打开,动作也没有被禁用,加速键还是触发了这个行为。
9.5.7 工具栏
工具栏是在程序中提供快速访问常用命令的按钮栏。
工具栏的特殊之处在于可以把它移到任何地方,可以把它拖拽到框架的四个边界上。释放鼠标按钮后,工具栏就停放在新的位置上。
注意:只有工具栏在具有边界布局或者其他任何支持North、East、South和West约束布局管理器的容器内才能被拖拽。
9.5.8 工具提示
在Swing中,可以调用setToolText方法将工具提示添加到任何一个JConmonent组件上:
exitButton.setToolTipText("Exit");
9.6 复杂的布局管理
提示:如果没有一种布局模式满足需求,就可以将窗口表面分割成多个独立的面板。然后,用另一种布局管理器组织这些面板。
注意:有些对象也扩展了Component类,但是他们不是用户界面组件,不能被插入到容器中。像JFrame和JApplet这样的顶层窗口就不能放置在其他窗口和面板中。
9.6.1 箱式布局
箱式布局要比网格布局灵活得多,他可以布局单行或单列组件。甚至容器——Box类的默认布局管理器就是BoxLayout。
提示:遗憾的是,BoxLayout将把组件增大到超过首先的尺寸。特别是文本域的最大宽度和高度具备设置成Integer.MAX_VALUE;也就是说,必要的话,它们将任意增大。如果使用箱式布局来管理文本域,该文本域就会变得非常大。这个问题的解决方法是把最大尺寸设置为首选尺寸:
textField.setMaxmumSize(textField.getPreferredSize());
填充件
默认情况下,箱式布局中各组件之间是没有间距的。如果需要添加间距,可以添加不可见的填充件(filler)。有三种这样的填充件:
1)支柱 直接在组件间增加空间。
2)固定区 有点像一对支柱。它可以吧邻接组件分离开,并且会设置另一个方向上的最小尺寸。
3)胶水 可以用尽可能大的间距就爱你过组件分开。胶水(不可见)将把组件互相拉开,直至充满整个空间。
9.6.2 网格组布局
网格组布局是所有布局管理器之首。可以认为网格组布局是没有限制的网格布局。在网格组布局中,行和列的尺寸可以改变。可以通过将相邻的单元河北来适应更大的组件。组件不需要填充整个单元格区域,并可以指定他们在单元格内的对齐方式。
要想使用网格组布局管理器进行布局,必须进过下列过程:
1)建立GridBagLayout类型的对象。不需要指定网格的行数和列数。布局管理器会根据后面所给的信息猜测出来。
2)把GridBagLayout对象设置成组件的布局管理器。
3)为每个组件建立一个GridBagConstraints类型的对象。设置GridBagConstraints对象的域值以便制定组件在网格组中的布局方案。
4)最后通过下面的调用添加组件的约束:
add(component,constaints);
知道如何设置GridBagConstraints对象的状态是非常重要的。接下来将相信地介绍重要的约束。
1)gridx、gridy、gridwidth和gridheight参数
这些约束定义了组件在网格中的位置。gridx和gridy制定了被添加组件左上角的行和列的位置。gridwidth和gridheight值决定了组件占用的行数和列数。
2)增量字段
在网格组不进需要为每个区域设置增量字段(weightx和weighty)。如果增量字段设置为0,这个区域永远为初始尺寸。
从概念上讲,增量参数属于行和列的属性,而不属于摸个单独的单元格。但却需要在单元格上指定他们,这是因为网格布局并不暴露行和列。行和列的增量等于每行或每列单元格增量的最大值。因此,如果想让一行或一列的大小保持不变,就需要把该行、该列的所有组件的增量都设置为0。
4)fill和anchor参数
如果不希望组件拉伸至整个区域,就需要设置fill约束。它有四个有效值:GridBagConstraints.NONE、GridBagConstraints.HORIZONTAL、GridBagConstraints.VERTICAL和GridBagConstraints.BOTH。
如果组件没有填充整个区域,可以通过设置anchor字段来指定其位置。有效值为GridBagConstraints.CENTER、GridBagConstraints.NORTH、GridBagConstraints.NORTHEAST、GridBagConstraints.EAST等。
4)填塞
通过设置GridBagLayout的insets字段来在组件周围增加附加的空白区域。通过设置Insets对象的left、top、right和bottom值来设置主键周围的空间量。这被称作外部填塞(external padding)。
用ipadx和ipady值设置内部填塞(internal padding)。这两个值将被添加到组件的最小宽度和最小高度上。这样可以保证组件不会收缩至最小尺寸之下。
5)指定gridx、gridy、gridwidth、gridheight参数的另一种方法
9.6.3 弹簧布局 2010-10-10 407页
9.6.4 不使用布局管理器
9.6.5 定制布局管理器
原则上,可以通过自己设计的LayoutManager类来实现特殊的布局方式。
9.6.6 遍历顺序
当把很多组件添加到窗口中时,需要考虑遍历顺序(traversal order)的问题。窗口初次显示时,遍历顺序的第一个组件会有键盘焦点。每次用户按下TAB键,下一个组件就会获得焦点。
遍历顺序很直观,它的顺序是从左至右,从上到下。
注意:在早先的AWT中,遍历顺序是有主见插入容器中的顺序决定的。在Swing中,插入顺序无关紧要,仅考虑组件的布局。
9.7 对话框
9.7.1 选项对话框
Swing 具有一组简单的对话框,用于收集用户的一些简单信息。JOptionPane有四个用于显示这些简单对话框的静态方法:
showMessageDialog 显示一条消息并等待用户点击OK
showConfirmDialog 显示一条信息并等待用户确认(与OK/Cancel类似)
showOptionDialog 显示一条信息并得到用户在一组选项中的选择
showInputDialog 显示一条信息并得到用户的一行输入
9.7.2 创建对话框
9.7.3 数据交换
注意:无模式对话框数据传输就没那么简单了。当无模式对话框显示时,对于setVisible(true)方法并不阻塞,在对话框显示时其他程序仍在继续运行。如果用户选择了无模式对话框中的一项,并点击OK,对话框就会把一个事件发送到程序中的某个监听器。
9.7.4 文件对话框
若想限制显示的文件,需要创建一个扩展了抽象类javax.swing.filechooser.FileFilter的对象。文件选择器把每个文件传递给文件过滤器,只有文件过滤器接受的文件才被最终显示出来。
注意:在java.io包中有一个不相关的FileFilter接口,它只有一个方法:boolean accept(File f)。它被File类中的listFiles方法用来显示目录中的文件。
警告:如果为加载和保存不同类型的文件重用一个文件选择器,则调用
chooser.resetChooseableFilters()
就可以在添加新过滤器之前清除旧的文件过滤器。
9.7.5 颜色选择器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值