zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java Swing用户界面组件:复选框+ 滑块+组合框+边界+单选按钮

JAVA组件 组合 按钮 边界 复选框 单选 用户界面
2023-06-13 09:14:11 时间

选择组件

前面已经讲述了如何获取用户输入的文本。但是在很多情况下,可能更加愿意给用户几种选择而不是让用户在文本组件中输入数据。给一组按钮或者一列选项让用户做出选择。(这样也免去了检查错误的麻烦。)在本节中,将介绍如何编写程序实现复选框、单选按钮、选项列表以及滑块。

复选框

如果想要接收的输入只是“是”或“非”,就可以使用复选框组件。复选框自动地带有标识标签。用户通过点击某个复选框来选择相应的选项,再点击则取消选择。当复选框获得焦点时,用户也可以通过按空格键来切换选择。

图9-15所示的程序中有两个复选框,其中一个用于打开或关闭字体斜体属性,而另一个用于加粗属性。注意第二个复选框有焦点,这一点可以由它周围的矩形框看出。只要用户点击某个复选框,程序就会刷新屏幕以便应用新的字体属性。

复选框需要一个紧邻它的标签来说明其用途。在构造器中指定标签文本。

bold = new JCheckBox("Bold");

可以使用setSelected方法选定或取消复选框。例如:

bold.setSelected(true);

isSelected方法将返回每个复选框的当前状态。如果没有选择则为false,否则为true。

当用户点击复选框时将触发一个动作事件。通常,可以为复选框设置一个动作监听器。在下面程序中,两个复选框使用了同一个动作监听器。

actionPerformed方法查询bold和italic两个复选框的状态,并且把面板中的字体设置为常规、加粗、斜体或者粗斜体。

例9-5给出了复选框的全部代码。

例9-5 CheckBoxTest.java

javax.swing.JCheckBox 1.2

• JCheckBox(String label)

用给定的标签构造一个复选框,该标签初始化为“未选”。

• JCheckBox(String label, boolean state)

用给定的标签和初始化状态构造一个复选框。

• JCheckBox(String label, Icon icon)

用给定的标签与初始化为“未选”的图标构造一个复选框。

• boolean isSelected ( )

返回复选框状态。

• void setSelected(boolean state)

将复选框设置为新的状态。

单选按钮

在前一个例子中,对于两个复选框来说,用户可以选择一个、两个或者两个都不选。在很多情况下,我们需要用户只选择几个选项当中的一个。当用户选择另一个的时候,前一个就会自动地取消选择。这样一组框通常称为单选按钮组(radio button group),这是因为这些按钮的工作像收音机上的电台选择按钮。当按下一个按钮时,

前一个按下的按钮就自动地弹起。图9-16显示了典型的例子。这里允许用户在多个选择中选择字体的大小—小、中、大和超大—但是,每次只能选择一个选项。

在Swing中实现单选按钮组非常简单。为单选按钮组构造一个ButtonGroup类型的对象。

然后,把JRadioButton类型的对象添加到按钮组中。按钮组对象负责当新按钮被按下时取消前一个按下的操作。

如果按钮初始状态已选择,构造器的第二个参数为true,同时其他按钮构造器的这个参数为false。注意,按钮组仅仅控制按钮的行为,如果想把这些按钮组织在一起布局,需要把它们添加到容器中,如JPanel。

看一下图9-15和图9-16,会发现单选按钮的外观不同于复选框。复选框为正方形,并且如果被选择,该正方形中会出现一个对钩的符号。单选按钮是圆形,选择以后圈内出现一个圆点。

单选按钮的事件通告机制与任何其他按钮一样。当用户点击一个单选按钮时,该按钮产生一个动作事件。在例子中,定义了一个动作监听器用来把字体大小设置为新值:

对比这个监听器和复选框中的监听器。每个单选按钮都对应一个不同的监听器对象。每个监听器对象都非常明确它需要做什么—把字体尺寸设置为一个特定值。在复选框例子中,使用的是一种不同的方法。两个复选框共享一个动作监听器。这个监听器调用一个方法来检查两个复选框的当前状态。

对于单选按钮来说,能够使用同一种方法吗?可以试一下使用一个监听器计算尺寸,如

if (smallButton.isSelected()) size = 8;

else if (mediumButton. isSelected()) size = 12;

. . .

然而,我们更愿意使用独立的动作监听器对象,因为这样可以把尺寸值和按钮紧密地绑定在一起。

例9-6是一个用于选择字体大小的完整的程序,它演示了单选按钮的工作过程。

例9-6 RadioButtonTest.java

javax.swing.JRadioButton 1.2

• JRadioButton(String label, boolean state)

用给定的标签和初始状态构造一个单选按钮。

• JRadioButton(String label, Icon icon)

用给定的标签和图标构造一个初始化为“未选”的单选按钮。

javax.swing.ButtonGroup 1.2

• void add(AbstractButton b)

将该按钮添加到组中。

• ButtonModel getSelection( )

返回该按钮的按钮模型。

javax.swing.ButtonModel 1.2

• String getActionCommand( )

返回这个按钮模型的动作命令。

javax.swing.AbstractButton 1.2

• void setActionCommand(String s)

设置这个按钮及其模型的动作命令。

边界

如果在一个窗口中有多组单选按钮,那么就需要用可视化的形式明确地指出哪些按钮属于同一组。Swing提供了一组有用的边界(border)来解决这个问题。可以在任何继承了JComponent的组件上应用边界。最常见的是在一个面板周围设置边界,然后用其他用户界面元素(如单选按钮)来填充面板。

有几种不同的边界可供选择,但是使用它们的步骤完全一样。

1)调用BorderFactory的静态方法创建边界。下面是几种可选的风格(如图9-17所示):

• 凹斜面

• 凸斜面

• 蚀刻

• 直线

• 不光滑

2)如果愿意的话,可以给边界添加标题,具体实现方法是将边界传递给:

BorderFactory.createTitledBorder.

3)如果确实想将边框凸显出来,可以调用下列方法把几种边界组合起来使用:

BorderFactory.createCompoundBorder.

4)调用JComponent类中setBorder方法将结果边界添加到组件中。

例如,下面代码说明了如何把一个带有标题的蚀刻边界添加到一个面板上:

Border etched = BorderFactory.createEtchedBorder( )

Border titled = BorderFactory.createTitledBorder(etched, "A Title");

panel.setBorder(titled);

运行例9-7中的程序可以看到各种边界的外观。

不同的边界有着不同的用于设置边界的宽度和颜色的选项。详情请参看API注释。真正的边界爱好者欣赏这一点,有一个SoftBevelBorder类用于具有柔和拐角的斜面边界;有一个LineBorder类用于弄圆拐角。这些边界只能通过这些类的某个构造器构造,它们没有BorderFactory方法。

例9-7 BorderTest.java

javax.swing.BorderFactory 1.2

• static Border createLineBorder(Color color)

• static Border createLineBorder(Color color, int thickness)

创建一个简单的直线边界。

• static MatteBorder createMatteBorder(int top, int left, int bottom, int right, Color color)

• static MatteBorder createMatteBorder(int top, int left, int bottom, int right, Icon tileIcon)

创建一个用颜色或一个重复(repeating)图标填充的粗边界。

• static Border createEmptyBorder( )

• static Border createEmptyBorder(int top, int left, int bottom, int right)

创建一个空边界。

• static Border createEtchedBorder( )

• static Border createEtchedBorder(Color highlight, Color shadow)

• static Border createEtchedBorder(int type)

• static Border createEtchedBorder(int type, Color highlight, Color shadow)

创建一个具有3D效果的直线边界。

参数:highlight, shadow

用于3D效果的颜色

type EtchedBorder.RAISED和EtchedBorder.LOWERED之一

• static Border createBevelBorder(int type)

• static Border createBevelBorder(int type, Color highlight, Color shadow)

• static Border createLoweredBevelBorder( )

• static Border createRaisedBevelBorder( )

创建具有凹面或凸面效果的边界。

参数:type BevelBorder.LOWERED和BevelBorder.RAISED之一

highlight, shadow

用于3D效果的颜色

• static TitledBorder createTitledBorder(String title)

• static TitledBorder createTitledBorder(Border border)

• static TitledBorder createTitledBorder(Border border, String title)

• static TitledBorder createTitledBorder(Border border, String title, int justification, int position)

• static TitledBorder createTitledBorder(Border border, String title, int justification, int position, Font font)

• static TitledBorder createTitledBorder(Border border, String title, int justification, int position, Font font, Color color)

创建一个具有给定特性的带标题的边框。

参数:title 标题字符串

border 用标题装饰的边界

justification TitledBorder常量LEFT、CENTER、RIGHT、LEADING、TRAILING或

DEFAULT_JUSTIFICATION (left) 之一

position TitledBorder常量ABOVE_TOP、TOP、BELOW_TOP、ABOVE_BOTTOM、

BOTTOM、BELOW_BOTTOM或DEFAULT_POSITION (top) 之一

font 标题的字体

color 标题的颜色

• static CompoundBorder createCompoundBorder(Border outsideBorder, Border insideBorder)

将两个边界组合成一个新的边界。

javax.swing.border.SoftBevelBorder 1.2

• SoftBevelBorder(int type)

• SoftBevelBorder(int type, Color highlight, Color shadow)

创建带有柔和角的斜面边界。

参数:type BevelBorder.LOWERED和BevelBorder.RAISED之一

highlight, shadow

用于3D效果的颜色

javax.swing.border.LineBorder 1.2

• public LineBorder(Color color, int thickness, boolean roundedCorners)

用指定的颜色和宽度创建一个直线边界。如果roundedCorners为true,则边界具有圆拐角。

javax.swing.JComponent 1.2

• void setBorder(Border border)

设置这个组件的边界。

组合框

如果有多个选择项,使用单选按钮就不太合适了,其原因是占据的屏幕空间太大。这时可以选择组合框。

当用户点击这个组件时,选择列表就会下拉出来,用户可以从中选择一项(见图9-18)。

如果下拉列表框被设置成可编辑的(editable),可以像编辑文本域一样编辑当前的选项内容。正因为这个原因,这种组件被称为组合框(combo box),它把文本域的灵活性与一组预定义的选项组合起来。JComboBox类提供了组合框的组件。

调用setEditable方法可以编辑组合框。注意编辑只会影响当前项,而不改变列表内容。

在例子中,用户可以选择字体风格列表(Serif、SansSerif、Monospaced等)选择字体。用户也可以键入其他的字体。

调用addItem增加选项。在示例程序中,只在构造器中调用addItem,实际上可以在任何位置调用它。

faceCombo = new JComboBox( );

faceCombo.setEditable(true);

faceCombo.addItem("Serif");

faceCombo.addItem("SansSerif");

. . .

这个方法将字符串添加到列表结尾。可以使用insertItemAt方法指定新项在列表中的插入位置:

faceCombo.insertItemAt("Monospaced", 0); // add at the beginning

可以增加任何类型的项—组合框将调用每项的toString方法显示其内容。

如果需要在运行时删除某些项,可以使用removeItem或者removeItemAt方法,使用哪个方法将取决于参数提供的是要删除的选项还是位置。

faceCombo.removeItem("Monospaced");

faceCombo.removeItemAt(0); // remove first item

removeAllItems方法将立即移除所有的选项。

提示:如果需要往组合框中添加大量的选项,addItem方法的性能就显得很差了。取而代之的是可以构造一个DefaultComboBoxModel,并调用addElement方法进行加载,然后再调用JComboBox类中的setModel方法。

当用户从组合框中选择一个选项时,组合框就会产生一个动作事件。为了判断哪个选项被选择,可以在事件参数上调用getSource方法来得到发送事件的组合框的一个引用。接着调用getSelectedItem方法获取当前选择的项。需要把这个方法的返回值转化为合适的类型,通常是String型。

例9-8给出了完整的代码。

注意:如果希望持久性地显示列表而不是下拉列表,就应该使用JList组件。在卷II的第6章将介绍JList。

例9-8 ComboBoxTest.java

javax.swing.JComboBox 1.2

• void setEditable(boolean b)

参数:b 如果组合框域可编辑则为true,否则为false

• void addItem(Object item)

将一个选项添加到选项列表中。

• void insertItemAt(Object item, int index)

将一个选项插入到选项列表的指定位置。

• void removeItem(Object item)

从选项列表删除一个选项。

• void removeItemAt(int index)

删除指定位置的选项。

• void removeAllItems( )

从选项列表中删除所有选项。

• Object getSelectedItem( )

返回当前所选的选项。

滑块

组合框允许用户从一组离散值中进行选择。滑块允许进行连续值的选择,例如,选择从1~100的任何一个数值。

通常构造滑块的方法如下:

JSlider slider = new JSlider(min, max, initialValue);

如果忽略最小值、最大值和初始值,那么这三个选项分别默认为0、100和50。

如果需要一个垂直的滑块,可以调用如下的构造器:

JSlider slider = new JSlider(SwingConstants.VERTICAL, min, max, initialValue);

这个构造器构造了一个无格式的滑块,如图9-19上面所示。下面将看一下如何为滑块添加装饰。

当用户滑动滑块时,滑块的值就会在最小值和最大值之间变化。当值发生变化时,ChangeEvent事件就会向所有的改变监听器发出通知。为了得到这些改变的通知,需要调用addChangeListener方法并且安装实现了ChangeListener接口的对象。这个接口只有一个方法StateChanged。

在这个方法中,可以获取滑块的当前值:

public void stateChanged(ChangeEvent event){
JSlider slider = (JSlider) event.getSource( );int value = slider.getValue( );
. . .
}

可以通过显示标尺(tick)对滑块进行修饰。例如,在示例程序中,第二个滑块使用了如下的设置:

slider.setMajorTickSpacing(20);

slider.setMinorTickSpacing(5);

上述滑块在每20个单元的位置显示一个的大标尺,每5个单元的位置显示一个小标尺标记。

所谓单元值就是滑块值,而不是像素值。

这些代码只是设置了标尺标记。要将它们实际地显示出来,还需要调用:

slider.setPaintTicks(true);

大标尺和小标尺是独立的。例如,可以为每20个单元设置一个大标尺,同时每7个单元设置一个小标尺,但是这样设置,滑块看起来有可能非常凌乱。

可以强制滑块对齐标尺。在这种模式下,只要用户拖放滑块结束,滑块就会马上自动移到最近的标尺处。激活此模式需要调用:

slider.setSnapToTicks(true);

注意:“对齐标尺”行为与想象的工作过程并不太一样。在滑块真正对齐之前,改变监听器一直报告并不对应标尺的滑块值,如果点击滑块附近,滑块通常向点击方向移动一小段距离,“对齐标尺”的滑块并不移动到下一个标尺处。

可以给大标尺添加标尺标签(tick mark label),调用方法:

slider.setPaintLabels(true);

例如,对于一个范围在0~100的滑块,如果大标尺的间距是20,每个大标尺的标签就应该是0、20、40、60、80和100。

也可以提供其他标尺标记,如字符串或者图标(见图9-19)。这样做有些麻烦。需要填充一个键为Integer类型而值为Component类型的散列表(在JDK 5.0中,自动打包可以使这个过程容易很多)。然后调用setLabelTable方法,组件就会放置在标尺标记处。通常使用JLabel对象。下面代码说明如何把标尺标签设置为A、B、C、D、E和F。

Hashtable<Integer, Component> labelTable = new Hashtable<Integer, Component>( );
labelTable.put(, new JLabel("A"));
labelTable.put(, new JLabel("B"));
. . .
labelTable.put(, new JLabel("F"));
slider.setLabelTable(labelTable);

关于散列表的详细介绍,参看卷II的第2章。

例9-9显示了如何创建用图标作为标尺标签的滑块。

提示:如果标尺标记或标签不显示,请检查确认调用了setPaintTicks(true)和etPaintLabels(true)。

忽略滑块移动的轨迹,调用:

slider.setPaintTrack(false);

图9-19中第四个滑块就没有轨迹。

第五个滑块是逆向的,调用:

slider.setInverted(true);

例9-9中的程序演示了所有不同视觉效果的滑块。每个滑块都安装了一个改变事件监听器,它负责把当前的滑块值显示到框架底部的文本域中。

例9-9 SliderTest.java

javax.swing.JSlider 1.2

• JSlider( )

• JSlider(int direction)

• JSlider(int min, int max)

• JSlider(int min, int max, int initialValue)

• JSlider(int direction, int min, int max, int initialValue)

使用给定的方向、最大值、最小值和初始化值创建一个水平滑块。

参数:direction SwingConstants.HORIZONTAL或SwingConstants.VERTICAL之一。默认为水平

min, max 滑块值的最小值、最大值。默认值为0~100

initialValue 滑块的初始化值。默认值为50

• void setPaintTicks(boolean b)

如果b为true显示标尺。

• void setMajorTickSpacing(int units)

• void setMinorTickSpacing(int units)

用给定的滑块单元的倍数,设置大标尺和小标尺。

• void setPaintLabels(boolean b)

如果b是true,显示标尺标签。

• void setLabelTable(Dictionary table)

设置用于标尺标签的组件。表中的每一个键/值对都采用new Integer(value)/component的格式。

• void setSnapToTicks(boolean b)

如果b是true,每一次调整滑块都将对齐到最近的标尺处。

• void setPaintTrack(boolean b)

如果b是true,显示滑块滑动的轨迹。

JSpinner组件

JSpinner是带有两个小按钮的文本域。当点击它时,可以增加或减少文本域的值(见图9-20)。

在微调控制器(spinner)中的值可以是数字、日期、来自列表的值以及任何可以用上一个和下一个决定值的序列。JSpinner类为前三种情况定义了标准的数据模型,还可以自定义数据模型来描述任意的序列。

在默认情况下,微调控制器管理整数,并且按钮点击增加1或减少1。通过调用getValue方法可以获取当前的值。此方法返回Object,需要将它转化为Integer,并得到包装后的值。

JSpinner defaultSpinner = new JSpinner( );

. . .

int value = (Integer) defaultSpinner.getValue( );

可以改变增量,让它不为1,还可以提供更大或更小的边界值。下面的微调控制器,初始值为5,边界值为0和10,增量为0.5:

JSpinner boundedSpinner = new JSpinner(new SpinnerNumberModel(5, 0, 10, 0.5));

有两个SpinnerNumberModel构造器,一个带int参数,另一个带double参数。一旦某个参数是浮点值,就会调用第二个构造器。这个构造器将值设置为Double对象。

微调控制器没有限定只能是数值类型,可以构造一个在任何值的集合中迭代的微调控制器。

只要将SpinnerListModel传递给JSpinner构造器即可。也可以用数组或者实现了List接口的类(像ArrayList)构造SpinnerListModel。在下面的示例程序中,微调控制器控制着所有可能的字体名称。

String[ ] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment( ).getAvailableFontFamilyNames( );

JSpinner listSpinner = new JSpinner(new SpinnerListModel(fonts));

然而,发现迭代的方向有点混乱,这是因为与用户使用的组合框刚好相反。在组合框中,较大的值在较小的值下面,所以可以用向下的键来得到较大的值。但是微调控制器将对数组的下标进行增量迭加,因此向上的键才能得到较大的值。在SpinnerListModel中没有提供逆转顺序的方法,然而可以使用一个临时的匿名子类实现这种结果:

试试这两个版本,看看哪个更合适。

微调控制器的另一个应用就是让用户增减日期。要想得到这样一个微调控制器,并初始化为今天的日期,需要调用:

然而,仔细看一下图9-20,就会发现微调控制器文本显示了日期和时间,如

这里显示的时间对于日期收集器来说没有任何用途。要想让微调控制器只显示日期有些难度,下面是一段修改代码:

使用同样的方法,可以得到一个日期收集器。利用SpinnerDateModel构造器指定一个Date,上下边界(null表示没有边界)和需要修改的Calendar域(比如Calendar.HOUR)。

如果想将增量修改为15分钟,标准SpinnerDateModel类就显得力不从心了。

可以在微调控制器中自定义微调控制器模型显示任意的序列。在我们的示例程序中,有一个微调控制器,可以在字符串“meat”的排列中循环。可以通过点击微调控制器按钮来获得20个排列的字符串“mate”、“meta”、“team”。

在自定义模型时,应该扩展AbstractSpinnerModel类,并定义下面四个方法:

getValue方法返回存储在模型中的值,setValue方法设置一个新值。如果新值不合适,就会抛出一个IllegalArgumentException异常。

警告:在调用setValue方法设置新值之后,必须调用fireStateChanged方法,否则微调控制器不会更新。

getNextValue和getPreviousValue方法返回当前值的下一个或者上一个值,如果到了边界则返回null。

警告:getNextValue和getPreviousValue方法不改变当前值。当用户点击微调控制器的向上箭头,将调用getNextVaule方法。如果返回值不为null,调用setValue进行设置。

在例9-10中,使用了一个标准算法决定前后顺序。在这里,算法细节并不重要。

例9-10显示了如何产生多种微调控制器类型。可以通过点击Ok按钮来查看微调控制器的值。

例9-10 SpinnerTest.java

javax.swing.JSpinner 1.4

• JSpinner( )

构造一个编辑整数的微调控制器,初始值为0,增量为1,没有边界。

• JSpinner(SpinnerModel model)

构造一个使用给定数据模型的微调控制器。

• Object getValue( )

得到微调控制器的当前值。

• void setValue(Object value)

尝试设置微调控制器的值。如果该模型不能接受该值,抛出IllegalArgumentException异常。

• void setEditor(JComponent editor)

设置用于编辑微调控制器的值的组件。

javax.swing.SpinnerNumberModel 1.4

• SpinnerNumberModel(int initval, int minimum, int maximum, int stepSize)

• SpinnerNumberModel(double initval, double minimum, double maximum, double stepSize)

这些构造器产生管理Integer或Double类型的值的数字模型。无边界的值使用Integer和Double类的常量MIN_VALUE和MAX_VALUE定义。

参数:initval 初始值

minimum 最小有效值

maximum 最大有效值

stepSize 每次微调的增量或减量

javax.swing.SpinnerListModel 1.4

• SpinnerListModel(Object[ ] values)

• SpinnerListModel(List values)

这些构造器产生从给定值中选出一个值的模型。

javax.swing.SpinnerDateModel 1.4

• SpinnerDateModel( )

构造一个日期模型,用今天的日期作为初始值,没有下边界与上边界(no lower or upperbounds)增量为Calendar.DAY_OF_MONTH。

• SpinnerDateModel(Date initval, Comparable minimum, Comparable maximum, int step)

参数:initval 初始值

minimum 最小有效值,如果不想要下边界则为null

maximum 最大有效值,如果不想要上边界则为null

step 日期域每一次微调的增量或减量。Calendar类的下述常量之一:

ERA、YEAR、MONTH、WEEK_OF_YEAR、WEEK_OF_MONTH、

DAY_OF_MONTH 、 DAY_OF_YEAR 、 DAY_OF_WEEK 、

DAY_OF_WEEK_IN_MONTH、AM_PM、HOUR、HOUR_OF_DAY、

MINUTE、SECOND或MILLISECOND

java.text.SimpleDateFormat 1.1

• String toPattern( ) 1.2

得到这个日期格式器的编辑模式。一种典型的模式是“yyyy-MM-dd”。有关模式的详细的信息请参看JDK文档。

javax.swing.JSpinner.DateEditor 1.4

• DateEditor(JSpinner spinner, String pattern)

为微调控制器构造一个日期编辑器。

参数:spinner 编辑器所属的微调控制器

pattern 与SimpleDateFormat相关的格式模式

javax.swing.AbstractSpinnerModel 1.4

• Object getValue( )

得到该模型的当前值。

• void setValue(Object value)

给模型设置一个新值。如果该值不可接受,则抛出IllegalArgumentException异常。当覆盖这个方法时,在设置新值之后应该调用fireStateChanged。

• Object getNextValue( )

• Object getPreviousValue( )

计算(但是不设置)该模型定义序列中的下一个或上一个值。

今天就讲到这里,喜欢的朋友可以转发关注一下!!!

明天给大家分享GUI应用程序中的下拉式菜单~~~~~~

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。