JAVA swing

Swing 是新一代的图形界面工具。使用 Swing 来开发图形界面比 AWT 更加优秀,因为 Swing 是一种轻量级组件,它采用纯 Java 实现,不再依赖于本地平台的图形界面,所以可以在所有平台上保持相同的运行效果,对跨平台支持比较出色。除此之外,Swing 提供了比 AWT 更多的图形界面组件,因此可以开发出美观的图形界面程序。

目录

Swing 类库结构

Swing 包

Swing 容器

JFrame 窗口

JPane

l 面板

布局管理器

边框布局管理器

流式布局管理器

卡片布局管理器

网格布局管理器

网格包布局管理器

盒布局管理器

JLable:标签组件

JButton:按钮组件

JTextField:单行文本框组件

JTextArea:文本域组件

JCheckBox:复选框组件

JRadioButton:单选按钮组件

JComboBox:下拉列表组件

JList:列表框组件

Swing计算器界面的实现

事件监听:事件处理模型和事件监听器

事件处理模型

动作事件监听器

焦点事件监听器

监听列表项选择事件

星座选择器界面的实现

JSlider:滑块组件

JProgressBar:进度条组件

Timer:计时器组件

JMenu和JPopupMenu:菜单和弹出式菜单

JMenu 类的常用方法

弹出式菜单 JPopuMenu

JToolBar:工具栏组件

JFileChooser和JColorChooser:文件选择器和颜色选择器

文件选择器

颜色选择器

JOptionPane:对话框组件

确认对话框

消息对话框

输入对话框

选项对话框

JTable:表格

JTree:树组件

JTabbedPane:选项卡组件

文本编辑器的实现


Swing 类库结构

Swing 组件都采用 MVC(Model-View-Controller,即模型-视图-控制器)的设计,实现 GUI 组件的显示逻辑和数据逻辑的分离,从而允许程序员自定义 Render 来改变 GUI 组件的显示外观,以提供更多的灵活性。

Swing 围绕 JComponent 组件构建,JComponent 则由 AWT 的容器类扩展而来。Swing 组织结构如图 1 所示。

Swing类库组织结构图

图1 Swing类库组织结构图

从图 1 可以看出,Swing 组件除了 AbstmctButton 类之外都以 J 开头。Swing 容器组件直接继承 AWT 类库中的容器组件类,其他大部分组件都是继承 JComponet 组件。组件可以划分为容器组件和非容器组件,容器组件包括 JFmme 和 JDialog。其中 JComponent 定义了非容器类的轻量级组件(JBntton、JPanel、JMenu 等)。

Swing 包

Swing 类库由许多包组成,通过这些包中的类相互协作来完成 GUI 设计。其中,javax.swing 包是 Swing 提供的最大包,它包含将近 100 个类和 25 个接口。几乎所有 Swing 组件都在该包中。表 1 列出了常用的 Swing 包。

包名称描述
javax.swing提供一组“轻量级”组件,尽量让这些组件在所有平台上的工作方式都相同
javax.swing.border提供围绕 Swing 组件绘制特殊边框的类和接口
javax.swing.event提供 Swing 组件触发的事件
javax.swing.filechooser提供 JFileChooser 组件使用的类和接口
javax.swing.table提供用于处理 javax.swing.JTable 的类和接口
javax.swing.text提供类 HTMLEditorKit 和创建 HTML 文本编辑器的支持类
javax.swing.tree提供处理 javax.swingJTree 的类和接口

javax.swing.event 包中定义了事件和事件监听器类,javax.swing.event 包与 AWT 的 event 包类似。Java.awt.event 和 javax.swing.event 都包含事件类和监听器接口,它们分别响应由 AWT 组件和 Swing 组件触发的事件。

例如,当在树组件中需要节点扩展(或折叠)的通知时,则要实现 Swing 的 TreeExpansionListener 接口,并把一个 TreeExpansionEvent 实例传送给 TreeExpansionListener 接口中定义的方法,而 TreeExpansionListener 和 TreeExpansionEvent 都是在 swing.event 包中定义的。

虽然 Swing 的表格组件(JTable)在 javax.swing 包中,但它的支持类却在 javax.swing.table 包中。表格模型、图形绘制类和编辑器等也都在 javax.swing.table 包中。

与 JTable 类一样,Swing 中的树 JTree(用于按层次组织数据的结构组件)也在 javax.swing 包中,而它的支持类却在 javax.swing.tree 包中。javax.swing.tree 包提供树模型、树节点、树单元编辑类和树绘制类等支持类。

Swing 容器

创建图形用户界面程序的第一步是创建一个容器类以容纳其他组件,常见的窗口就是一种容器。容器本身也是一种组件,它的作用就是用来组织、管理和显示其他组件。

Swing 中容器可以分为两类:顶层容器和中间容器。

顶层容器是进行图形编程的基础,一切图形化的东西都必须包括在顶层容器中。顶层容器是任何图形界面程序都要涉及的主窗口,是显示并承载组件的容器组件。在 Swing 中有三种可以使用的顶层容器,分别是 JFrame、JDialog 和 JApplet。

  1. JFrame:用于框架窗口的类,此窗口带有边框、标题、关闭和最小化窗口的图标。带 GUI 的应用程序至少使用一个框架窗口。

  2. JDialog:用于对话框的类。

  3. JApplet:用于使用 Swing 组件的 Java Applet 类。

中间容器是容器组件的一种,也可以承载其他组件,但中间容器不能独立显示,必须依附于其他的顶层容器。常见的中间容器有 JPanel、JScrollPane、JTabbedPane 和 JToolBar。

  • JPanel:表示一个普通面板,是最灵活、最常用的中间容器。

  • JScrollPane:与 JPanel 类似,但它可在大的组件或可扩展组件周围提供滚动条。

  • JTabbedPane:表示选项卡面板,可以包含多个组件,但一次只显示一个组件,用户可在组件之间方便地切换。

  • JToolBar:表示工具栏,按行或列排列一组组件(通常是按钮)。

在 Java 程序中容器类都是继承自 Container 类。中间容器和顶层容器在,AWT 包和 Swing 包中继承 Container 类的继承关系,如图 2 所示。

img

图2 容器类组织结构图

JFrame 窗口

JFrame 用来设计类似于 Windows 系统中窗口形式的界面。JFrame 是 Swing 组件的顶层容器,该类继承了 AWT 的 Frame 类,支持 Swing 体系结构的高级 GUI 属性。

JFrame 类的常用构造方法如下所示。

  • JFrame():构造一个初始时不可见的新窗体。

  • JFrame(String title):创建一个具有 title 指定标题的不可见新窗体。

当创建一个 JFrame 类的实例化对象后,其他组件并不能够直接放到容器上面,需要将组件添加至内容窗格,而不是直接添加至 JFrame 对象。示例代码如下:

frame.getContentPane().add(b);

使用 JFrame 类创建 GUI 界面时,其组件的布局组织示意如图 1 所示。

JFrame窗口组件组织

图1 JFrame窗口组件组织

在图 1 中显示有“大家好”的 Swing 组件需要放到内容窗格的上面,内容窗格再放到 JFrame 顶层容器的上面。菜单栏可以直接放到顶层容器 JFrame 上,而不通过内容窗格。内容窗格是一个透明的没有边框的中间容器。

JFrame 类中的常用方法如表 1 所示。

方法名称概述
getContentPane()返回此窗体的 contentPane 对象
getDefaultCloseOperation()返回用户在此窗体上单击“关闭”按钮时执行的操作
setContentPane(Container contentPane)设置 contentPane 属性
setDefaultCloseOperation(int operation)设置用户在此窗体上单击“关闭”按钮时默认执行的操作
setDefaultLookAndFeelDecorated (boolean defaultLookAndFeelDecorated)设置 JFrame 窗口使用的 Windows 外观(如边框、关 闭窗口的 小部件、标题等)
setIconImage(Image image)设置要作为此窗口图标显不的图像
setJMenuBar( JMenuBar menubar)设置此窗体的菜单栏
setLayout(LayoutManager manager)设置 LayoutManager 属性

例 1

在了解窗口组件 JFrame 的语法之后,下面使用 JFrame 类创建一个窗口。要求设置窗口的标题为“Java 第一个 GUI 程序”,并向窗口内添加“这是使用 JFrame 类创建的窗口”文本。具体实现代码如下:

package ch17;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.*;
public class JFrameDemo extends JFrame
{
    public JFrameDemo()
    {
        setTitle("Java 第一个 GUI 程序");    //设置显示窗口标题
        setSize(400,200);    //设置窗口显示尺寸
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //置窗口是否可以关闭
        JLabel jl=new JLabel("这是使用JFrame类创建的窗口");    //创建一个标签
        Container c=getContentPane();    //获取当前窗口的内容窗格
        c.add(jl);    //将标签组件添加到内容窗格上
        setVisible(true);    //设置窗口是否可见
    }
    public static void main(String[] agrs)
    {
        new JFrameDemo();    //创建一个实例化对象
    }
}

上述代码创建的 JFrameDemo 类继承了 JFrame 类,因此 JFrameDemo 类可以直接使用 JFrame 类的方法。setTitle() 方法用来设置窗口标题,setDefaultCloseOperation() 方法用来设置响应方式,即当单击“关闭”按钮时退出该程序。

在构造方法中使用 JLabel 类创建一个标签对象 jl,其参数是标签的文本提示信息。JFrame 框架的 getContentPane() 方法获取了内容窗格对象,并使用 add() 方法将标签添加到内容窗格上。最后的 setVisible() 方法是从父类中继承的方法。

程序运行的窗口结果如图 2 所示。

窗口运行结果

图2 窗口运行结果

JPane

l 面板

JPanel 是一种中间层容器,它能容纳组件并将组件组合在一起,但它本身必须添加到其他容器中使用。JPanel 类的构造方法如下。

  • JPanel():使用默认的布局管理器创建新面板,默认的布局管理器为 FlowLayout。

  • JPanel(LayoutManagerLayout layout):创建指定布局管理器的 JPanel 对象。

JPanel 类的常用方法如表 2 所示。

方法名及返回值类型说明
Component add(Component comp)将指定的组件追加到此容器的尾部
void remove(Component comp)从容器中移除指定的组件
void setFont(Font f)设置容器的字体
void setLayout(LayoutManager mgr)设置容器的布局管理器
void setBackground(Color c)设置组件的背景色

例 2

编写一个使用 JPanel 组件的窗口程序。要求设置标题为“Java的第二个GUI程序”,然后向窗口中添加一个面板,并设置面板上显示的文本为“这是放在JPanel上的标签”,设置面板背景颜色为白色。具体实现代码如下:

package ch17;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.*;
public class JPanelDemo
{   
    public static void main(String[] agrs)
    {
        JFrame jf=new JFrame("Java第二个GUI程序");    //创建一个JFrame对象
        jf.setBounds(300, 100, 400, 200);    //设置窗口大小和位置
        JPanel jp=new JPanel();    //创建一个JPanel对象
        JLabel jl=new JLabel("这是放在JPanel上的标签");    //创建一个标签
        jp.setBackground(Color.white);    //设置背景色
        jp.add(jl);    //将标签添加到面板
        jf.add(jp);    //将面板添加到窗口
        jf.setVisible(true);    //设置窗口可见
    }
}

如上述代码,首先创建了一个 JFrame 对象,并设置其大小和位置,然后创建了一个 JPanel对象表示面板,调用 setBackground() 方法设置面板的背景色为白色,调用 add() 方法将标签添加到此面板。JFrame 类的 add() 方法将 JPanel 面板添加到 JFmme 窗口中。最后调用 setVisible() 方法将窗口设置为可见。

运行程序,显示的窗口如图 3 所示。

面板显示效果

图3 面板显示效果

布局管理器

在使用 Swing 向容器添加组件时,需要考虑组件的位置和大小。如果不使用布局管理器,则需要先在纸上画好各个组件的位置并计算组件间的距离,再向容器中添加。这样虽然能够灵活控制组件的位置,实现却非常麻烦。

为了加快开发速度,Java 提供了一些布局管理器,它们可以将组件进行统一管理,这样开发人员就不需要考虑组件是否会重叠等问题。本节介绍 Swing 提供的 6 种布局类型,所有布局都实现 LayoutManager 接口。

边框布局管理器

BorderLayout(边框布局管理器)是 Window、JFrame 和 JDialog 的默认布局管理器。边框布局管理器将窗口分为 5 个区域:North、South、East、West 和 Center。其中,North 表示北,将占据面板的上方;Soufe 表示南,将占据面板的下方;East表示东,将占据面板的右侧;West 表示西,将占据面板的左侧;中间区域 Center 是在东、南、西、北都填满后剩下的区域,如图 1 所示。

框布局管理器区域划分示意图

图1 边框布局管理器区域划分示意图

提示:边框布局管理器并不要求所有区域都必须有组件,如果四周的区域(North、South、East 和 West 区域)没有组件,则由 Center 区域去补充。如果单个区域中添加的不只一个组件,那么后来添加的组件将覆盖原来的组件,所以,区域中只显示最后添加的一个组件。

BorderLayout 布局管理器的构造方法如下所示。

  • BorderLayout():创建一个 Border 布局,组件之间没有间隙。

  • BorderLayout(int hgap,int vgap):创建一个 Border 布局,其中 hgap 表示组件之间的横向间隔;vgap 表示组件之间的纵向间隔,单位是像素。

例 1

使用 BorderLayout 将窗口分割为 5 个区域,并在每个区域添加一个标签按钮。实现代码如下:

package ch17;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.*;
public class BorderLayoutDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java第三个GUI程序");    //创建Frame窗口
        frame.setSize(400,200);
        frame.setLayout(new BorderLayout());    //为Frame窗口设置布局为BorderLayout
        JButton button1=new JButton ("上");
        JButton button2=new JButton("左");
        JButton button3=new JButton("中");
        JButton button4=new JButton("右");
        JButton button5=new JButton("下");
        frame.add(button1,BorderLayout.NORTH);
        frame.add(button2,BorderLayout.WEST);
        frame.add(button3,BorderLayout.CENTER);
        frame.add(button4,BorderLayout.EAST);
        frame.add(button5,BorderLayout.SOUTH);
        frame.setBounds(300,200,600,300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

在该程序中分别指定了 BorderLayout 布局的东、南、西、北、中间区域中要填充的按钮。该程序的运行结果如图 2 所示。

填充5个区域的效果

图2 填充5个区域的效果

如果未指定布局管理器的 NORTH 区域,即将“frame.add(button1,BorderLayout.NORTH);”注释掉,则 WEST、CENTER 和 EAST 3 个区域将会填充 NORTH 区域,如图 3 所示。

缺少 NORTH 区域

图3 缺少NORTH区域

同理,如果未指定布局管理器的 WEST 区域,即将“frame.add(button2,BorderLayout.WEST);”注释掉,则 CENTER 区域将会自动拉伸填充 WEST 区域,如图 4 所示。

缺少 WEST 区域

图4 缺少WEST区域

流式布局管理器

FlowLayout(流式布局管理器)是 JPanel 和 JApplet 的默认布局管理器。FlowLayout 会将组件按照从上到下、从左到右的放置规律逐行进行定位。与其他布局管理器不同的是,FlowLayout 布局管理器不限制它所管理组件的大小,而是允许它们有自己的最佳大小。

FlowLayout 布局管理器的构造方法如下。

  • FlowLayout():创建一个布局管理器,使用默认的居中对齐方式和默认 5 像素的水平和垂直间隔。

  • FlowLayout(int align):创建一个布局管理器,使用默认 5 像素的水平和垂直间隔。其中,align 表示组件的对齐方式,对齐的值必须是 FlowLayoutLEFT、FlowLayout.RIGHT 和 FlowLayout.CENTER,指定组件在这一行的位置是居左对齐、居右对齐或居中对齐。

  • FlowLayout(int align, int hgap,int vgap):创建一个布局管理器,其中 align 表示组件的对齐方式;hgap 表示组件之间的横向间隔;vgap 表示组件之间的纵向间隔,单位是像素。

例 2

创建一个窗口,设置标题为“Java第四个GUI程序”。使用 FlowLayout 类对窗口进行布局,向容器内添加 9 个按钮,并设置横向和纵向的间隔都为 20 像素。具体实现代码如下:

package ch17;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.*;
public class FlowLayoutDemo
{
    public static void main(String[] agrs)
    {
        JFrame jFrame=new JFrame("Java第四个GUI程序");    //创建Frame窗口
        JPanel jPanel=new JPanel();    //创建面板
        JButton btn1=new JButton("1");    //创建按钮
        JButton btn2=new JButton("2");
        JButton btn3=new JButton("3");
        JButton btn4=new JButton("4");
        JButton btn5=new JButton("5");
        JButton btn6=new JButton("6");
        JButton btn7=new JButton("7");
        JButton btn8=new JButton("8");
        JButton btn9=new JButton("9");
        jPanel.add(btn1);    //面板中添加按钮
        jPanel.add(btn2);
        jPanel.add(btn3);
        jPanel.add(btn4);
        jPanel.add(btn5);
        jPanel.add(btn6);
        jPanel.add(btn7);
        jPanel.add(btn8);
        jPanel.add(btn9);
        //向JPanel添加FlowLayout布局管理器,将组件间的横向和纵向间隙都设置为20像素
        jPanel.setLayout(new FlowLayout(FlowLayout.LEADING,20,20));
        jPanel.setBackground(Color.gray);    //设置背景色
        jFrame.add(jPanel);    //添加面板到容器
        jFrame.setBounds(300,200,300,150);    //设置容器的大小
        jFrame.setVisible(true);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述程序向 JPanel 面板中添加了 9 个按钮,并使用 HowLayout 布局管理器使 9 个按钮间的横向和纵向间隙都为 20 像素。此时这些按钮将在容器上按照从上到下、从左到右的顺序排列,如果一行剩余空间不足容纳组件将会换行显示,最终运行结果如图 5 所示。

FlowLayout布局按钮结果

FlowLayout布局按钮结果

图5 FlowLayout布局按钮结果

卡片布局管理器

CardLayout(卡片布局管理器)能够帮助用户实现多个成员共享同一个显不空间,并且一次只显示一个容器组件的内容。

CardLayout 布局管理器将容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件。CardLayout 的构造方法如下。

  • CardLayout():构造一个新布局,默认间隔为 0。

  • CardLayout(int hgap, int vgap):创建布局管理器,并指定组件间的水平间隔(hgap)和垂直间隔(vgap)。

例 3

使用 CardLayout 类对容器内的两个面板进行布局。其中第一个面板上包括三个按钮,第二个面板上包括三个文本框。最后调用 CardLayout 类的 show() 方法显示指定面板的内容,代码如下:

package ch17;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.*;
public class CardLayoutDemo
{   
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java第五个程序");    //创建Frame窗口
        JPanel p1=new JPanel();    //面板1
        JPanel p2=new JPanel();    //面板2
        JPanel cards=new JPanel(new CardLayout());    //卡片式布局的面板
        p1.add(new JButton("登录按钮"));
        p1.add(new JButton("注册按钮"));
        p1.add(new JButton("找回密码按钮"));
        p2.add(new JTextField("用户名文本框",20));
        p2.add(new JTextField("密码文本框",20));
        p2.add(new JTextField("验证码文本框",20));
        cards.add(p1,"card1");    //向卡片式布局面板中添加面板1
        cards.add(p2,"card2");    //向卡片式布局面板中添加面板2
        CardLayout cl=(CardLayout)(cards.getLayout());
        cl.show(cards,"card1");    //调用show()方法显示面板2
        frame.add(cards);
        frame.setBounds(300,200,400,200);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述代码创建了一个卡片式布局的面板 cards,该面板包含两个大小相同的子面板 p1 和 p2。需要注意的是,在将 p1 和 p2 添加到 cards 面板中时使用了含有两个参数的 add() 方法,该方法的第二个参数用来标识子面板。当需要显示某一个面板时,只需要调用卡片式布局管理器的 show() 方法,并在参数中指定子面板所对应的字符串即可,这里显示的是 p1 面板,运行效果如图 6 所示。

显示 p1 面板

图6 显示p1面板

如果将“cl.show(cards,"card1")”语句中的 card1 换成 card2,将显示 p2 面板的内容,此时运行结果如图 7 所示。

显示 p2 面板

图7 显示p2面板

网格布局管理器

GridLayout(网格布局管理器)为组件的放置位置提供了更大的灵活性。它将区域分割成行数(rows)和列数(columns)的网格状布局,组件按照由左至右、由上而下的次序排列填充到各个单元格中。

GridLayout 的构造方法如下。

  • GridLayout(int rows,int cols):创建一个指定行(rows)和列(cols)的网格布局。布局中所有组件的大小一样,组件之间没有间隔。

  • GridLayout(int rows,int cols,int hgap,int vgap):创建一个指定行(rows)和列(cols)的网格布局,并且可以指定组件之间横向(hgap)和纵向(vgap)的间隔,单位是像素。

提示:GridLayout 布局管理器总是忽略组件的最佳大小,而是根据提供的行和列进行平分。该布局管理的所有单元格的宽度和高度都是一样的。

例 4

使用 GridLayout 类的网格布局设计一个简单计算器。代码的实现如下:

package ch17;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.*;
public class GridLayoutDemo
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("GridLayou布局计算器");
        JPanel panel=new JPanel();    //创建面板
        //指定面板的布局为GridLayout,4行4列,间隙为5
        panel.setLayout(new GridLayout(4,4,5,5));
        panel.add(new JButton("7"));    //添加按钮
        panel.add(new JButton("8"));
        panel.add(new JButton("9"));
        panel.add(new JButton("/"));
        panel.add(new JButton("4"));
        panel.add(new JButton("5"));
        panel.add(new JButton("6"));
        panel.add(new JButton("*"));
        panel.add(new JButton("1"));
        panel.add(new JButton("2"));
        panel.add(new JButton("3"));
        panel.add(new JButton("-"));
        panel.add(new JButton("0"));
        panel.add(new JButton("."));
        panel.add(new JButton("="));
        panel.add(new JButton("+"));
        frame.add(panel);    //添加面板到容器
        frame.setBounds(300,200,200,150);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述程序设置面板为 4 行 4 列、间隙都为 5 像素的网格布局,在该面板上包含 16 个按钮,其横向和纵向的间隙都为 5。该程序的运行结果如图 8 所示。

计算器

图8 计算器

网格包布局管理器

GridBagLayout(网格包布局管理器)是在网格基础上提供复杂的布局,是最灵活、 最复杂的布局管理器。GridBagLayout 不需要组件的尺寸一致,允许组件扩展到多行多列。每个 GridBagLayout 对象都维护了一组动态的矩形网格单元,每个组件占一个或多个单元,所占有的网格单元称为组件的显示区域。

GridBagLayout 所管理的每个组件都与一个 GridBagConstraints 约束类的对象相关。这个约束类对象指定了组件的显示区域在网格中的位置,以及在其显示区域中应该如何摆放组件。除了组件的约束对象,GridBagLayout 还要考虑每个组件的最小和首选尺寸,以确定组件的大小。

为了有效地利用网格包布局管理器,在向容器中添加组件时,必须定制某些组件的相关约束对象。GridBagConstraints 对象的定制是通过下列变量实现的。

1. gridx 和 gridy

用来指定组件左上角在网格中的行和列。容器中最左边列的 gridx 为 0,最上边行的 gridy 为 0。这两个变量的默认值是 GridBagConstraints.RELATIVE,表示对应的组件将放在前一个组件的右边或下面。

2. gridwidth 和 gridheight

用来指定组件显示区域所占的列数和行数,以网格单元而不是像素为单位,默认值为 1。

3. fill

指定组件填充网格的方式,可以是如下值:GridBagConstraints.NONE(默认值)、GridBagConstraints.HORIZONTAL(组件横向充满显示区域,但是不改变组件高度)、GridBagConstraints.VERTICAL(组件纵向充满显示区域,但是不改变组件宽度)以及 GridBagConstraints.BOTH(组件横向、纵向充满其显示区域)。

4. ipadx 和 ipady

指定组件显示区域的内部填充,即在组件最小尺寸之外需要附加的像素数,默认值为 0。

5. insets

指定组件显示区域的外部填充,即组件与其显示区域边缘之间的空间,默认组件没有外部填充。

6. anchor

指定组件在显示区域中的摆放位置。可选值有 GridBagConstraints.CENTER(默认值)、GridBagConstraints.NORTH、GridBagConstraints. NORTHEAST、GridBagConstraints.EAST、GridBagConstraints.SOUTH、GridBagConstraints.SOUTHEAST、GridBagConstraints.WEST、GridBagConstraints.SOUTHWEST 以及 GridBagConstraints.NORTHWEST。

7. weightx 和 weighty

用来指定在容器大小改变时,增加或减少的空间如何在组件间分配,默认值为 0,即所有的组件将聚拢在容器的中心,多余的空间将放在容器边缘与网格单元之间。weightx 和 weighty 的取值一般在 0.0 与 1.0 之间,数值大表明组件所在的行或者列将获得更多的空间。

例 5

创建一个窗口,使用 GridBagLayout 进行布局,实现一个简易的手机拨号盘。这里要注意如何控制行内组件的显示方式以及使用 GridBagConstraints.REMAINDER 来控制一行的结束。代码的实现如下:

package ch17;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.*;
public class GridLayoutDemo
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("GridLayou布局计算器");
        JPanel panel=new JPanel();    //创建面板
        //指定面板的布局为GridLayout,4行4列,间隙为5
        panel.setLayout(new GridLayout(4,4,5,5));
        panel.add(new JButton("7"));    //添加按钮
        panel.add(new JButton("8"));
        panel.add(new JButton("9"));
        panel.add(new JButton("/"));
        panel.add(new JButton("4"));
        panel.add(new JButton("5"));
        panel.add(new JButton("6"));
        panel.add(new JButton("*"));
        panel.add(new JButton("1"));
        panel.add(new JButton("2"));
        panel.add(new JButton("3"));
        panel.add(new JButton("-"));
        panel.add(new JButton("0"));
        panel.add(new JButton("."));
        panel.add(new JButton("="));
        panel.add(new JButton("+"));
        frame.add(panel);    //添加面板到容器
        frame.setBounds(300,200,200,150);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

在上述程序中创建了一个 makeButton() 方法,用来将 JButton 组件添加到 JFrame 窗口中。在 main() 方法中分别创建了 GridBagLayout 对象和 GridBagConstraints 对象,然后设置 JFrame 窗口的布局为 GridBagLayout,并设置了 GridBagConstraints 的一些属性。接着将 JTextField 组件添加至窗口中,并通知布局管理器的 GridBagConstraints 信息。

在接下来的代码中,调用 makeButton() 方法向 JFrame 窗口填充按钮,并使用 GridBagConstraints. REMAINDER 来控制结束行。当一行结束后,重新设置 GridBagConstraints 对象的 gridwidth 为 1。最后设置 JFrame 窗口为可见状态,程序运行后的拨号盘效果如图 9 所示。

拨号盘运行效果

图9 拨号盘运行效果

盒布局管理器

BoxLayout(盒布局管理器)通常和 Box 容器联合使用,Box 类有以下两个静态方法。

  • createHorizontalBox():返回一个 Box 对象,它采用水平 BoxLayout,即 BoxLayout 沿着水平方向放置组件,让组件在容器内从左到右排列。

  • createVerticalBox():返回一个 Box 对象,它采用垂直 BoxLayout,即 BoxLayout 沿着垂直方向放置组件,让组件在容器内从上到下进行排列。

Box 还提供了用于决定组件之间间隔的静态方法,如表 1 所示。

网格包布局说明
static Component createHorizontalGlue()创建一个不可见的、可以被水平拉伸和收缩的组件
static Component createVerticalGlue()创建一个不可见的、可以被垂直拉伸和收缩的组件
static Component createHorizontalStrut(int width)创建一个不可见的、固定宽度的组件
static Component createVerticalStrut(int height)创建一个不可见的、固定高度的组件
static Component createRigidArea(Dimension d)创建一个不可见的、总是具有指定大小的组件

BoxLayout 类只有一个构造方法,如下所示。

BoxLayout(Container c,int axis)

其中,参数 Container 是一个容器对象,即该布局管理器在哪个容器中使用;第二个参数为 int 型,用来决定容器上的组件水平(X_AXIS)或垂直(Y_AXIS)放置,可以使用 BoxLayout 类访问这两个属性。

例 6

使用 BoxLayout 类对容器内的 4 个按钮进行布局管理,使两个按钮为横向排列,另外两个按钮为纵向排列,代码如下:

package ch17;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.*;
public class BoxLayoutDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java示例程序");
        Box b1=Box.createHorizontalBox();    //创建横向Box容器
        Box b2=Box.createVerticalBox();    //创建纵向Box容器
        frame.add(b1);    //将外层横向Box添加进窗体
        b1.add(Box.createVerticalStrut(200));    //添加高度为200的垂直框架
        b1.add(new JButton("西"));    //添加按钮1
        b1.add(Box.createHorizontalStrut(140));    //添加长度为140的水平框架 
        b1.add(new JButton("东"));    //添加按钮2
        b1.add(Box.createHorizontalGlue());    //添加水平胶水
        b1.add(b2);    //添加嵌套的纵向Box容器
        //添加宽度为100,高度为20的固定区域  
        b2.add(Box.createRigidArea(new Dimension(100,20))); 
        b2.add(new JButton("北"));    //添加按钮3
        b2.add(Box.createVerticalGlue());    //添加垂直组件
        b2.add(new JButton("南"));    //添加按钮4
        b2.add(Box.createVerticalStrut(40));    //添加长度为40的垂直框架
        //设置窗口的关闭动作、标题、大小位置以及可见性等  
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setBounds(100,100,400,200); 
        frame.setVisible(true); 
    }
}

在程序中创建了 4 个 JButton 按钮和两个 Box 容器(横向 Box 容器和纵向 Box 容器),并将前两个 JButton 按钮添加到横向 Box 容器中,将后两个 JButton 容器添加到纵向 Box 容器中。程序的运行结果如图 10 所示。

BoxLayout运行结果

图10 BoxLayout运行结果

提示:使用盒式布局可以像使用流式布局一样简单地将组件安排在一个容器内。包含盒式布局的容器可以嵌套使用,最终达到类似于无序网格布局那样的效果,却不像使用无序网格布局那样麻烦。

JLable:标签组件

标签是一种可以包含文本和图片的非交互组件,其文本可以是单行文本,也可以是 HTML 文本。对于只包含文本的标签可以使用 JLabel 类,该类的主要构造方法有如下几种形式。

  • JLabel():创建无图像并且标题为空字符串的 JLabel。

  • JLabel(Icon image):创建具有指定图像的 JLabel。

  • JLabel(String text):创建具有指定文本的 JLabel。

  • JLabel(String textjcon image,int horizontalAlignment):创建具有指定文本、图像和水平对齐方式的 JLabel,horizontalAlignment 的取值有 3 个,即 JLabel.LEFT、JLabel.RIGHT 和 JLabel.CENTER。

JLabel 的常用方法如表 1 所示。

方法名称说明
void setText(Stxing text)定义 JLabel 将要显示的单行文本
void setIcon(Icon image)定义 JLabel 将要显示的图标
void setIconTextGap(int iconTextGap)如果 JLabel 同时显示图标和文本,则此属性定义它们之间的间隔
void setHorizontalTextPosition(int textPosition)设置 JLabel 的文本相对其图像的水平位置
void setHorizontalAlignment(int alignment)设置标签内容沿 X 轴的对齐方式
int getText()返回 JLabel 所显示的文本字符串
Icon getIcon()返回 JLabel 显示的图形图像
Component getLabelFor()获得将 JLabel 添加到的组件
int getIconTextGap()返回此标签中显示的文本和图标之间的间隔量
int getHorizontalTextPosition()返回 JLabel 的文本相对其图像的水平位置
int getHorizontalAlignment()返回 JLabel 沿 X 轴的对齐方式

例 1

使用 JFrame 组件创建一个窗口,然后向窗口中添加 3 个标签,这 3 个标签分别使用不同的创建方法。实现代码如下:

​
package ch17;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JLabelDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java标签组件示例");    //创建Frame窗口
        JPanel jp=new JPanel();    //创建面板
        JLabel label1=new JLabel("普通标签");    //创建标签
        JLabel label2=new JLabel();
        label2.setText("调用setText()方法");
        ImageIcon img=new ImageIcon("D:\\money.png");    //创建一个图标
        //创建既含有文本又含有图标的JLabel对象
        JLabel label3=new JLabel("开始理财",img,JLabel.CENTER);
        jp.add(label1);    //添加标签到面板
        jp.add(label2);
        jp.add(label3);
        frame.add(jp);
        frame.setBounds(300,200,400,100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
​

程序运行后在窗口中将显示 3 个标签,效果如图 1 所示。

标签显示效果

图1 标签显示效果

JButton:按钮组件

按钮是图形界面上常见的元素,在前面已经多次使用过它。在 Swing 中按钮是 JButton 类的对象,JButton 类的常用构造方法如下。

  • JButton():创建一个无标签文本、无图标的按钮。

  • JButton(Icon icon):创建一个无标签文本、有图标的按钮。

  • JButton(String text):创建一个有标签文本、无图标的按钮。

  • JButton(String text,Icon icon):创建一个有标签文本、有图标的按钮。

JButton 类的常用方法如表 1 所示。

方法名称说明
addActionListener(ActionListener listener)为按担组件注册 ActionListener 监听
void setIcon(Icon icon)设置按钮的默认图标
void setText(String text)设置按鈕的文本
void setMargin(Insets m)设置按钮边框和标签之间的空白
void setMnemonic(int nmemonic)设置按钮的键盘快捷键,所设置的快捷键在实际操作时需要结合 Alt 键进行实现
void setPressedIcon(Icon icon)设置按下按钮时的图标
void setSelectedIcon(Icon icon)设置选择按鈕时的图标
void setRolloveiicon(Icon icon)设置鼠标移动到按扭区域时的图标
void setDisabledIcon(Icon icon)设置按钮无效状态下的图标
void setVerticalAlignment(int alig)设置图标和文本的垂直对齐方式
void setHorizontalAlignment(int alig)设置图标和文本的水平对齐方式
void setEnable(boolean flag)启用或禁用按扭
void setVerticalTextPosition(int textPosition)设置文本相对于图标的垂直位置
void setHorizontalTextPosition(int textPosition)设置文本相对于图标的水平位置

例 1

使用 JFrame 组件创建一个窗口,然后创建 4 个不同类型的按钮,再分别添加到窗口上显示。具体代码如下:

package ch17;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class JButtonDemo
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("Java按钮组件示例");    //创建Frame窗口
        frame.setSize(400, 200);
        JPanel jp=new JPanel();    //创建JPanel对象
        JButton btn1=new JButton("我是普通按钮");    //创建JButton对象
        JButton btn2=new JButton("我是带背景颜色按钮");
        JButton btn3=new JButton("我是不可用按钮");
        JButton btn4=new JButton("我是底部对齐按钮");
        jp.add(btn1);
        btn2.setBackground(Color.YELLOW);    //设置按钮背景色
        jp.add(btn2);
        btn3.setEnabled(false);    //设置按钮不可用
        jp.add(btn3);
        Dimension preferredSize=new Dimension(160, 60);    //设置尺寸
        btn4.setPreferredSize(preferredSize);    //设置按钮大小
        btn4.setVerticalAlignment(SwingConstants.BOTTOM);    //设置按钮垂直对齐方式
        jp.add(btn4);
        frame.add(jp);
        frame.setBounds(300, 200, 600, 300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述代码创建了 1 个 JFrame 窗口对象、1 个 JPanel 面板对象和 4 个 JButton 按钮,然后调用 JButton 类的 setBackground() 方法、setEnabled() 方法、setPreferredSize() 方法和 setVerticalAlignment() 方法设置按钮的显示外观。程序运行后 4 个按钮显示效果如图 1 所示。

按钮显示

图1 按钮显示

JTextField:单行文本框组件

Swing 中使用 JTextField 类实现一个单行文本框,它允许用户输入单行的文本信息。该类的常用构造方法如下。

  • JTextField():创建一个默认的文本框。

  • JTextField(String text):创建一个指定初始化文本信息的文本框。

  • JTextField(int columns):创建一个指定列数的文本框。

  • JTextField(String text,int columns):创建一个既指定初始化文本信息,又指定列数的文本框。

JTextField 类的常用方法如表 1 所示。

方法名称说明
Dimension getPreferredSize()获得文本框的首选大小
void scrollRectToVisible(Rectangle r)向左或向右滚动文本框中的内容
void setColumns(int columns)设置文本框最多可显示内容的列数
void setFont(Font f)设置文本框的字体
void setScrollOffset(int scrollOffset)设置文本框的滚动偏移量(以像素为单位)
void setHorizontalAlignment(int alignment)设置文本框内容的水平对齐方式

例 1

使用 JPrame 组件创建一个窗口,然后向窗口中添加三个 JTextField 文本框。具体实现代码如下:

package ch17;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class JTextFieldDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java文本框组件示例");    //创建Frame窗口
        JPanel jp=new JPanel();    //创建面板
        JTextField txtfield1=new JTextField();    //创建文本框
        txtfield1.setText("普通文本框");    //设置文本框的内容
        JTextField txtfield2=new JTextField(28);
        txtfield2.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式
        txtfield2.setText("指定长度和字体的文本框");
        JTextField txtfield3=new JTextField(30);
        txtfield3.setText("居中对齐");
        txtfield3.setHorizontalAlignment(JTextField.CENTER);    //居中对齐
        jp.add(txtfield1);
        jp.add(txtfield2);
        jp.add(txtfield3);
        frame.add(jp);
        frame.setBounds(300,200,400,100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述程序中,第一个文本框 txtfield1 使用 JTextField 的默认构造方法创建;第二个文本框 txtfield2 在创建时指定了文本框的长度,同时还修改了文本的字体样式;第三个文本框 txtfield3 设置文本为居中对齐。

程序运行后在窗口中显示三个文本框,效果如图 1 所示。

文本框组件运行效果

图1 文本框组件运行效果

JTextArea:文本域组件

文本域与文本框的最大区别就是文本域允许用户输入多行文本信息。在 Swing 中使用 JTextArea 类实现一个文本域,其常用构造方法如下。

  • JTextArea():创建一个默认的文本域。

  • JTextArea(int rows,int columns):创建一个具有指定行数和列数的文本域。

  • JTextArea(String text):创建一个包含指定文本的文本域。

  • JTextArea(String text,int rows,int columns):创建一个既包含指定文本,又包含指定行数和列数的多行文本域。

JTextArea 类的常用方法如表 1 所示。

方法名称说明
void append(String str)将字符串 str 添加到文本域的最后位置
void setColumns(int columns)设置文本域的行数
void setRows(int rows)设置文本域的列数
int getColumns()获取文本域的行数
void setLineWrap(boolean wrap)设置文本域的换行策略
int getRows()获取文本域的列数
void insert(String str,int position)插入指定的字符串到文本域的指定位置
void replaceRange(String str,int start,int end)将指定的开始位 start 与结束位 end 之间的字符串用指定的字符串 str 取代

例 1

使用 JFrame 组件创建一个窗口,再向窗口中添加一个文本域,并将文本域中的文本设置为自动换行,允许显示滚动条。具体代码如下:

package ch17;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class JTextAreaDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java文本域组件示例");    //创建Frame窗口
        JPanel jp=new JPanel();    //创建一个JPanel对象
        JTextArea jta=new JTextArea("请输入内容",7,30);
        jta.setLineWrap(true);    //设置文本域中的文本为自动换行
        jta.setForeground(Color.BLACK);    //设置组件的背景色
        jta.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式
        jta.setBackground(Color.YELLOW);    //设置按钮背景色
        JScrollPane jsp=new JScrollPane(jta);    //将文本域放入滚动窗口
        Dimension size=jta.getPreferredSize();    //获得文本域的首选大小
        jsp.setBounds(110,90,size.width,size.height);
        jp.add(jsp);    //将JScrollPane添加到JPanel容器中
        frame.add(jp);    //将JPanel容器添加到JFrame容器中
        frame.setBackground(Color.LIGHT_GRAY);
        frame.setSize(400,200);    //设置JFrame容器的大小
        frame.setVisible(true);
    }
}
​

在上述代码中将 JTextArea 文本域放入滚动窗口中,并通过 getPreferredSize() 方法获得文本域的显示大小。将滚动窗口的大小设置成与文本域大小相同,再将滚动窗口添加到 JPanel 面板中。

运行程序,在文本域中可以输入多行内容,当内容超出文本域高度时会显示滚动条,如图 1 所示。

文本域运行效果

文本域运行效果

图1 文本域运行效果

JCheckBox:复选框组件

一个复选框有选中和未选中两种状态,并且可以同时选定多个复选框。Swing 中使用 JCheckBox 类实现复选框,该类的常用构造方法如下。

  • JCheckBox():创建一个默认的复选框,在默认情况下既未指定文本,也未指定图像,并且未被选择。

  • JCheckBox(String text):创建一个指定文本的复选框。

  • JCheckBox(String text,boolean selected):创建一个指定文本和选择状态的复选框。

例 1

使用 JFmme 组件创建一个窗口,然后使用 JCheckBox 类创建一些复选框。具体实现代码如下:

package ch17;
import java.awt.Font;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JCheckBoxDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java复选组件示例");    //创建Frame窗口
        JPanel jp=new JPanel();    //创建面板
        JLabel label=new JLabel("流行编程语言有:");
        label.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式
        JCheckBox chkbox1=new JCheckBox("C#", true);    //创建指定文本和状态的复选框
        JCheckBox chkbox2=new JCheckBox("C++");    //创建指定文本的复选框
        JCheckBox chkbox3=new JCheckBox("Java");    //创建指定文本的复选框
        JCheckBox chkbox4=new JCheckBox("Python");    //创建指定文本的复选框
        JCheckBox chkbox5=new JCheckBox("PHP");    //创建指定文本的复选框
        JCheckBox chkbox6=new JCheckBox("Perl");    //创建指定文本的复选框
        jp.add(label);
        jp.add(chkbox1);
        jp.add(chkbox2);
        jp.add(chkbox3);
        jp.add(chkbox4);
        jp.add(chkbox5);
        jp.add(chkbox6);
        frame.add(jp);
        frame.setBounds(300,200,400,100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
​

上述程序一共创建了 6 个复选框,其中第一个调用 JCheckBox 构造方法时指定了复选框为选中状态。程序的执行结果如图 1 所示。

复选框组件文本内容

图1 复选框组件文本内容

JRadioButton:单选按钮组件

单选按钮与复选框类似都有两种状态,不同的是一组单选按钮中只能有一个处于选中状态。Swing 中 JRadioButton 类实现单选按钮,它与 JCheckBox 一样都是从 JToggleButton 类派生出来的。JRadioButton 通常位于一个 ButtonGroup 按钮组中,不在按钮组中的 JRadioButton 也就失去了单选按钮的意义。

在同一个 ButtonGroup 按钮组中的单选按钮,只能有一个单选按钮被选中。因此,如果创建的多个单选按钮其初始状态都是选中状态,则最先加入 ButtonGroup 按钮组的单选按钮的选中状态被保留,其后加入到 ButtonGroup 按钮组中的其他单选按钮的选中状态被取消。

JRadioButton 类的常用构造方法如下。

  • JRadioButton():创建一个初始化为未选择的单选按钮,其文本未设定。

  • JRadioButton(Icon icon):创建一个初始化为未选择的单选按钮,其具有指定的图像但无文本。

  • JRadioButton(Icon icon,boolean selected):创建一个具有指定图像和选择状态的单选按钮,但无文本。

  • JRadioButton(String text):创建一个具有指定文本但未选择的单选按钮。

  • JRadioButton(String text,boolean selected):创建一个具有指定文本和选择状态的单选按钮。

  • JRadioButton(String text,Icon icon):创建一个具有指定的文本和图像并初始化为未选择的单选按钮。

  • JRadioButton(String text,Icon icon,boolean selected):创建一个具有指定的文本、图像和选择状态的单选按钮。

例 1

使用 JFrame 组件创建一个窗口,然后使用 JRadioButton 类创建一个选择季节的单选按钮组。实现代码如下:

package ch17;
import java.awt.Font;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class JRadioButtonDemo 
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("Java单选组件示例");    //创建Frame窗口
        JPanel panel=new JPanel();    //创建面板
        JLabel label1=new JLabel("现在是哪个季节:");
        JRadioButton rb1=new JRadioButton("春天");    //创建JRadioButton对象
        JRadioButton rb2=new JRadioButton("夏天");    //创建JRadioButton对象
        JRadioButton rb3=new JRadioButton("秋天",true);    //创建JRadioButton对象
        JRadioButton rb4=new JRadioButton("冬天");    //创建JRadioButton对象
        label1.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式
        ButtonGroup group=new ButtonGroup();
        //添加JRadioButton到ButtonGroup中
        group.add(rb1);
        group.add(rb2);
        panel.add(label1);
        panel.add(rb1);
        panel.add(rb2);
        panel.add(rb3);
        panel.add(rb4);
        frame.add(panel);
        frame.setBounds(300, 200, 400, 100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

在上述程序中创建了 4 个 JRadioButton 单选按钮,并将这 4 个单选按钮添加到 ButtonGroup 组件中。该程序的运行结果如图 1 所示。

JRadioButton 单选按钮

图1 JRadioButton 单选按钮

JComboBox:下拉列表组件

下拉列表的特点是将多个选项折叠在一起,只显示最前面的或被选中的一个。选择时需要单击下拉列表右边的下三角按钮,这时候会弹出包含所有选项的列表。用户可以在列表中进行选择,也可以根据需要直接输入所要的选项,还可以输入选项中没有的内容。

下拉列表由 JComboBox 类实现,常用构造方法如下。

  • JComboBox():创建一个空的 JComboBox 对象。

  • JComboBox(ComboBoxModel aModel):创建一个 JComboBox,其选项取自现有的 ComboBoxModel。

  • JComboBox(Object[] items):创建包含指定数组中元素的 JComboBox。

JComboBox 类提供了多个成员方法用于操作下拉列表框中的项,如表 1 所示。

方法名称说明
void addItem(Object anObject)将指定的对象作为选项添加到下拉列表框中
void insertItemAt(Object anObject,int index)在下拉列表框中的指定索引处插入项
void removeltem(0bject anObject)在下拉列表框中删除指定的对象项
void removeItemAt(int anlndex)在下拉列表框中删除指定位置的对象项
void removeAllItems()从下拉列表框中删除所有项
int getItemCount()返回下拉列表框中的项数
Object getItemAt(int index)获取指定索引的列表项,索引从 0 开始
int getSelectedIndex()获取当前选择的索引
Object getSelectedltem()获取当前选择的项

JComboBox 能够响应 ItemEvent 事件和 ActionEvent 事件,其中 ItemEvent 触发的时机是当下拉列表框中的所选项更改时,ActionEvent 触发的时机是当用户在 JComboBox 上直接输入选择项并回车时。要处理这两个事件,需要创建相应的事件类并实现 ItemListener 接口和 ActionListener 接口。

例 1

使用 JFrame 组件创建一个窗口,然后使用 JComboBox 类创建一个包含4个选项的下拉列表框。具体实现代码如下:

package ch17;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JComboBoxDemo
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("Java下拉列表组件示例");
        JPanel jp=new JPanel();    //创建面板
        JLabel label1=new JLabel("证件类型:");    //创建标签
        JComboBox cmb=new JComboBox();    //创建JComboBox
        cmb.addItem("--请选择--");    //向下拉列表中添加一项
        cmb.addItem("身份证");
        cmb.addItem("驾驶证");
        cmb.addItem("军官证");
        jp.add(label1);
        jp.add(cmb);
        frame.add(jp);
        frame.setBounds(300,200,400,100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述代码创建了一个下拉列表组件 cmb,然后调用 addItem() 方法向下拉列表中添加 4 个选项。运行后下拉列表的效果如图 1 所示。

下拉列表运行效果

图1 下拉列表运行效果

JList:列表框组件

列表框与下拉列表的区别不仅仅表现在外观上,当激活下拉列表时,会出现下拉列表框中的内容。但列表框只是在窗体系上占据固定的大小,如果需要列表框具有滚动效果,可以将列表框放到滚动面板中。当用户选择列表框中的某一项时,按住 Shift 键并选择列表框中的其他项目,可以连续选择两个选项之间的所有项目,也可以按住 Ctrl 键选择多个项目。

Swing 中使用 JList 类来表示列表框,该类的常用构造方法如下。

  • JList():构造一个空的只读模型的列表框。

  • JList(ListModel dataModel):根据指定的非 null 模型对象构造一个显示元素的列表框。

  • JList(Object[] listData):使用 listData 指定的元素构造—个列表框。

  • JList(Vector<?> listData):使用 listData 指定的元素构造一个列表框。

上述的第一个构造方法没有参数,使用此方法创建列表框后可以使用 setListData() 方法对列表框的元素进行填充,也可以调用其他形式的构造方法在初始化时对列表框的元素进行填充。常用的元素类型有 3 种,分别是数组、Vector 对象和 ListModel 模型。

例 1

使用 JFmme 组件创建一个窗口,然后使用 JList 类创建一个包含3个选项的列表框。具体实现代码如下:

package ch17;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
public class JListDemo
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("Java列表框组件示例");
        JPanel jp=new JPanel();    //创建面板
        JLabel label1=new JLabel("证件类型:");    //创建标签
        String[] items=new String[]{"身份证","驾驶证","军官证"};
        JList list=new JList(items);    //创建JList
        jp.add(label1);
        jp.add(list);
        frame.add(jp);
        frame.setBounds(300,200,400,100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

上述代码创建一个包含 3 个元素的字符串数组 items,然后将 items 作为参数来创建列表框。图 1 所示为实例运行后在列表框中的单选和多选效果。

列表框运行效果

图1 列表框运行效果

例 2

JList 组件在默认情况下支持单选和多选,可以通过 setSelectionMode() 方法来限制选择行为。例如,下面的代码将限制只能在列表框中进行单选操作。

package ch17;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
public class JListDemo1 extends JFrame
{
    public JListDemo1()
    {
        setTitle("Java列表框组件示例");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //设置窗体退出时操作
        setBounds(100,100,300,200);    //设置窗体位置和大小
        JPanel contentPane=new JPanel();    //创建内容面板
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));    //设置面板的边框
        contentPane.setLayout(new BorderLayout(0, 0));    //设置内容面板为边界布局
        setContentPane(contentPane);    //应用内容面板
        JScrollPane scrollPane=new JScrollPane();    //创建滚动面板
        contentPane.add(scrollPane,BorderLayout.CENTER);    //将面板增加到边界布局中央
        JList list=new JList();
        //限制只能选择一个元素
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        scrollPane.setViewportView(list);    //在滚动面板中显示列表
        String[] listData=new String[12];    //创建一个含有12个元素的数组
        for (int i=0;i<listData.length;i++)
        {
            listData[i]="这是列表框的第"+(i+1)+"个元素~";    //为数组中各个元素赋值
        }
        list.setListData(listData);    //为列表填充数据
    }
    public static void main(String[] args)
    {
        JListDemo1 frame=new JListDemo1();
        frame.setVisible(true);
    }
}

上述代码调用了 setSelectionMode() 方法,并指定 ListSelectionModel.SINGLE_SELECTION 常量来限制列表框一次只能选择一项。该方法还支持如下两个常量。

  1. ListSelectionModel.SINGLE_INTERVAL_SELECTION:允许选择一个或多个连续的元素。

  2. ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:允许选择一个连续的元素。

最终程序的运行效果如图 2 所示。

限制列表框单选运行效果

图2 限制列表框单选运行效果

Swing计算器界面的实现

在本节之前已经详细介绍了 Swing容器布局管理器以及常用的基本组件。本案例将综合运用这些知识实现一个计算器的布局。在本实例中使用两种布局管理器来进行界面设计。

计算器界面可以分成两部分,即显示区和键盘区。显示区可以使用文本框组件,键盘区则是由很多按钮组成,可以使用网格布局管理器。详细的实现过程如下。

(1) 新建一个继承自 JFrame 的 CalculatorDemo 类。

(2) 为类添加构造方法和 main() 方法,主要代码如下所示。

package ch17;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
public class CalculatorDemo extends JFrame
{
    private JPanel contentPane;    //内容面板
    private JTextField textField;    //文本框
    public CalculatorDemo(){};    //构造方法
    public static void main(String[] args)
    {
        CalculatorDemo frame=new CalculatorDemo();
        frame.setVisible(true);
    }
}

(3) 在构造方法中设置窗口的标题和大小等属性,然后使用边界面板向北部添加一个 JTextField 组件,主要代码如下所示。

public CalculatorDemo()
{
    setTitle("计算器");    //设置窗体的标题
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //设置窗体退出时操作
    setBounds(100, 100, 250, 200);    //设置窗体位置和大小
    contentPane=new JPanel();    //创建内容面板
    contentPane.setBorder(new EmptyBorder(5,5,5,5));    //设置面板的边框
    contentPane.setLayout(new BorderLayout(0,0));    //设置内容面板为边界布局
    setContentPane(contentPane);    //应用内容面板
    JPanel panel1=new JPanel();    //新建面板用于保存文本框
    contentPane.add(panel1,BorderLayout.NORTH);    //将面板放置在边界布局的北部
    textField=new JTextField();    //新建文本框
    textField.setHorizontalAlignment(SwingConstants.RIGHT);    //文本框中的文本使用右对齐
    panel1.add(textField);    //将文本框增加到面板中
    textField.setColumns(18);    //设置文本框的列数是18

(4) 接下来使用网格布局管理器添加多个按钮作为计算器的键盘区,主要代码如下所示。

JPanel panel2=new JPanel();    //新建面板用于保存按钮
contentPane.add(panel2, BorderLayout.CENTER);    //将面板放置在边界布局的中央
panel2.setLayout(new GridLayout(4,4,5,5));    //面板使用网格4X4布局
JButton button01=new JButton("7");    //新建按钮
panel2.add(button01);    //应用按钮
JButton button02=new JButton("8");    //新建按钮
panel2.add(button02);    //应用按钮
JButton button03=new JButton("9");    //新建按钮
panel2.add(button03);    //应用按钮
JButton button04=new JButton("+");    //新建按钮
panel2.add(button04);    //应用按钮
JButton button05=new JButton("4");    //新建按钮
panel2.add(button05);    //应用按钮
JButton button06=new JButton("5");    //新建按钮
panel2.add(button06);    //应用按钮
JButton button07=new JButton("6");    //新建按钮
panel2.add(button07);    //应用按钮
JButton button08=new JButton("-");    //新建按钮
panel2.add(button08);    //应用按钮
JButton button09=new JButton("3");    //新建按钮
panel2.add(button09);    //应用按钮
JButton button10=new JButton("2");    //新建按钮
panel2.add(button10);    //应用按钮
JButton button11=new JButton("1");    //新建按钮
panel2.add(button11);    //应用按钮
JButton button12=new JButton("*");    //新建按钮
panel2.add(button12);    //应用按钮
JButton button13=new JButton("0");    //新建按钮
panel2.add(button13);    //应用按钮
JButton button14=new JButton(".");    //新建按钮
panel2.add(button14);    //应用按钮
JButton button15=new JButton("=");    //新建按钮
panel2.add(button15);    //应用按钮
JButton button16=new JButton("/");    //新建按钮
panel2.add(button16);    //应用按钮

(5) 最终程序的运行效果如图 1 所示。

计算器布局效果

图1 计算器布局效果

事件监听:事件处理模型和事件监听器

事件表示程序和用户之间的交互,例如在文本框中输入,在列表框或组合框中选择,选中复选框和单选框,单击按钮等。事件处理表示程序对事件的响应,对用户的交互或者说对事件的处理是事件处理程序完成的。

当事件发生时,系统会自动捕捉这一事件,创建表示动作的事件对象并把它们分派给程序内的事件处理程序代码。这种代码确定了如何处理此事件以使用户得到相应的回答。

事件处理模型

前面我们讲解了如何放置各种组件,使图形界面更加丰富多彩,但是还不能响应用户的任何操作。若使图形界面能够接收用户的操作,必须给各个组件加上事件处理机制。在事件处理的过程中,主要涉及三类对象。

  • Event(事件):用户对组件的一次操作称为一个事件,以类的形式出现。例如,键盘操作对应的事件类是 KeyEvent。

  • Event Source(事件源):事件发生的场所,通常就是各个组件,例如按钮 Button。

  • Event Handler(事件处理者):接收事件对象并对其进行处理的对象事件处理器,通常就是某个 Java 类中负责处理事件的成员方法。

例如,如果鼠标单击了按钮对象 Button,则该按钮 Button 就是事件源,而 Java 运行时系统会生成 ActionEvent 类的对象 ActionEvent,该对象中描述了单击事件发生时的一些信息。之后,事件处理者对象将接收由 Java 运行时系统传递过来的事件对象 ActionEvent,并进行相应的处理。事件处理模型如图 1 所示。

事件处理模型

图1 事件处理模型

由于同一个事件源上可能发生多种事件,因此,Java 采取了授权模型(Delegation Model),事件源可以把在其自身上所有可能发生的事件分别授权给不同的事件处理者来处理。例如,在 Panel 对象上既可能发生鼠标事件,也可能发生键盘事件,该 Panel 对象可以授权给事件处理者 a 来处理鼠标事件,同时授权给事件处理者 b 来处理键盘事件。

有时也将事件处理者称为监听器,主要原因在于监听器时刻监听事件源上所有发生的事件类型,一旦该事件类型与自己所负责处理的事件类型一致,就马上进行处理。授权模型把事件的处理委托给外部的处理实体进行处理,实现了将事件源和监听器分开的机制。

事件处理者(监听器)通常是一个类,该类如果能够处理某种类型的事件,就必须实现与该事件类型相对的接口。例如,一个 ButtonHandler 类之所以能够处理 ActionEvent 事件,原因在于它实现了与 ActionEvent 事件对应的接口 ActionListener。每个事件类都有一个与之相对应的接口。

动作事件监听器

动作事件监听器是 Swing 中比较常用的事件监听器,很多组件的动作都会使用它监听,像按钮被里击、列表框中选择一项等。与动作事件监听器有关的信息如下。

  • 事件名称:ActionEvent。

  • 事件监听接口: ActionListener。

  • 事件相关方法:addActionListener() 添加监听,removeActionListener() 删除监听。

  • 涉及事件源:JButton、JList、JTextField 等。

例 1

下面以按钮的单击事件为例来说明动作单击事件监听器的应用。在此案例中统计了窗口内按钮被单击的次数。

本案例的核心代码如下:

package ch17;import java.awt.BorderLayout;import java.awt.Font;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JList;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;public class ActionListenerDemo extends JFrame{    JList list;    JLabel label;    JButton button1;    int clicks=0;    public ActionListenerDemo()    {        setTitle("动作事件监听器示例");        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        setBounds(100,100,400,200);        JPanel contentPane=new JPanel();        contentPane.setBorder(new EmptyBorder(5,5,5,5));        contentPane.setLayout(new BorderLayout(0,0));        setContentPane(contentPane);        label=new JLabel(" ");        label.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式        contentPane.add(label, BorderLayout.SOUTH);        button1=new JButton("我是普通按钮");    //创建JButton对象        button1.setFont(new Font("黑体",Font.BOLD,16));    //修改字体样式        button1.addActionListener(new ActionListener()        {            public void actionPerformed(ActionEvent e)            {                label.setText("按钮被单击了 "+(clicks++)+" 次");            }        });        contentPane.add(button1);    }    //处理按钮单击事件的匿名内部类    class button1ActionListener implements ActionListener    {        @Override        public void actionPerformed(ActionEvent e)        {            label.setText("按钮被单击了 "+(clicks++)+" 次");        }    }    public static void main(String[] args)    {        ActionListenerDemo frame=new ActionListenerDemo();        frame.setVisible(true);    }}

上述代码调用 addActionListener() 方法为 button1 添加了单击动作的事件监听器,该监听器由 button1ActionListener 类来实现。button1ActionListener 类必须继承 ActionListener 类,并重写父类的 actionPerformed() 方法。在 actionPerformed() 方法内编写按钮被单击后执行的功能。

图 2 所示为程序运行后,没有单击和单击后的效果。

处理按钮的单击事件

处理按钮的单击事件

图2 处理按钮的单击事件

在本例中使用的是内部类形式,当然也可以写成如下形式的代码:

//为按钮buttonl添加ActionEvent事件的处理程序buttonl.addActionListener(new ActionListener(){    public void action Performed(Action Event e)    {        //具体代码编写在这里        label.setTextC 按钮被单击了 "+(ciicks++)+1 次");    }}

焦点事件监听器

除了单击事件外,焦点事件监听器在实际项目中应用也比较广泛,例如将光标离开文本框时弹出对话框,或者将焦点返回给文本框等。

与焦点事件监听器有关的信息如下。

  • 事件名称:FocusEvent。

  • 事件监听接口: FocusListener。

  • 事件相关方法:addFocusListener() 添加监听,removeFocusListener() 删除监听。

  • 涉及事件源:Component 以及派生类。

FocusEvent 接口定义了两个方法,分别为 focusGained() 方法和 focusLost() 方法,其中 focusGained() 方法是在组件获得焦点时执行,focusLost() 方法是在组件失去焦点时执行。

例 2

下面以文本框的焦点事件为例来说明焦点单击事件监听器的应用。本案例的核心代码如下:

package ch17;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class FocusListenerDemo extends JFrame
{
    JList list;
    JLabel label;
    JButton button1;
    JTextField txtfield1;
    public FocusListenerDemo()
    {
        setTitle("焦点事件监听器示例");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100,100,400,200);
        JPanel contentPane=new JPanel();
        contentPane.setBorder(new EmptyBorder(5,5,5,5));
        contentPane.setLayout(new BorderLayout(0,0));
        setContentPane(contentPane);       
        label=new JLabel(" ");
        label.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式
        contentPane.add(label, BorderLayout.SOUTH);
        txtfield1=new JTextField();    //创建文本框
        txtfield1.setFont(new Font("黑体", Font.BOLD, 16));    //修改字体样式
        txtfield1.addFocusListener(new FocusListener()
        {
            @Override
            public void focusGained(FocusEvent arg0)
            {
                // 获取焦点时执行此方法
                label.setText("文本框获得焦点,正在输入内容");
            }
            @Override
            public void focusLost(FocusEvent arg0)
            {
                // 失去焦点时执行此方法
                label.setText("文本框失去焦点,内容输入完成");
            }
        });
        contentPane.add(txtfield1);
    }
    public static void main(String[] args)
    {
        FocusListenerDemo frame=new FocusListenerDemo();
        frame.setVisible(true);
    }
}

上述代码为 txtfield1 组件调用 addFocusListener() 方法添加了焦点事件监听器,并且监听器使用匿名的实现方式。在实现 FocusListener 接口的代码中编写 focusGained() 方法和 focusLost() 方法的代码。最终程序运行效果如图 3 所示。

处理文本框的焦点事件

图3 处理文本框的焦点事件

监听列表项选择事件

列表框控件 JList 会显示很多项供用户选择,通常在使用时会根据用户选择的列表项完成不同的操作。

本案例将介绍如何监听列表项的选择事件,以及事件监听器的处理方法,实现过程如下。

(1) 创建一个继承自 JFrame 的 JListDemo2 类。

(2) 在 JListDemo2 类中添加 JList 组件和 JLabel 组件的声明,并创建空的构造方法,代码如下所示。

package ch17;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class JListDemo2 extends JFrame
{
    JList list;
    JLabel label;
    public JListDemo2(){};
    public static void main(String[] args)
    {
        JListDemo2 frame=new JListDemo2();
        frame.setVisible(true);
    }
}

(3) 在构造方法中为列表框填充数据源,主要代码如下:

public JListDemo2()
{
    setTitle("监听列表项选择事件");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100,100,400,200);
    JPanel contentPane=new JPanel();
    contentPane.setBorder(new EmptyBorder(5,5,5,5));
    contentPane.setLayout(new BorderLayout(0,0));
    setContentPane(contentPane);
    label=new JLabel(" ");
    contentPane.add(label,BorderLayout.SOUTH);
    JScrollPane scrollPane=new JScrollPane();
    contentPane.add(scrollPane,BorderLayout.CENTER);
    list=new JList();
    scrollPane.setViewportView(list);
    String[] listData=new String[7];
    listData[0]="《一点就通学Java》";
    listData[1]="《一点就通学PHP》";
    listData[2]="《一点就通学Visual Basic)》";
    listData[3]="《一点就通学Visual C++)》";
    listData[4]="《Java编程词典》";
    listData[5]="《PHP编程词典》";
    listData[6]="《C++编程词典》";
    list.setListData(listData);
}

(4) 为列表框组件 list 添加选择事件监听,代码如下所示。

list.addListSelectionListener(new ListSelectionListener()
{
    public void valueChanged(ListSelectionEvent e)
    {
        do_list_valueChanged(e);
    }
});

如上述代码所示,list 组件绑定了 ListSelectionListener 事件监听器,在触发该事件后又会调用 do_list_valueChanged() 方法进行实际的业务逻辑处理。

(5) 创建 do_liSt_ValueChanged() 方法将用户选择的列显示到标签中,具体代码如下:

protected void do_list_valueChanged(ListSelectionEvent e)
{
    label.setText("感谢您购买:"+list.getSelectedValue());
}

(6) 运行程序,列表框选择前后的效果如图 4 所示。

选择事件触发前后运行效果

img

图4 选择事件触发前后运行效果

星座选择器界面的实现

在了解各种基本组件的使用,以及常见事件的处理之后,本案例将综合文本框、按钮下拉列表组件,实现一个星座选择器程序。程序允许用户在下拉列表中选择一个自己的星座,如果不在列表中还可以增加星座,也可以删除星座。实现过程如下。

(1) 创建一个 SampeDemo 类,在 main() 方法中调用它的构造方法。代码如下:

package ch17;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class SampeDemo
{
    public static void main(String[] args)
    {
        new SampeDemo();    //调用构造方法
    }
}

(2) 创建 SampeDemo 构造方法完成窗口的创建,按钮和下拉列表的添加,以及相应事件的监听。具体代码如下:

private JPanel panel=new JPanel();
private JComboBox cmb=new JComboBox();    //创建JComboBox
private JLabel label=new JLabel("添加新星座:");
private JLabel showInfo=new JLabel();    //用于显示信息
private JTextField jtf=new JTextField(16);    //用于输入信息
private JButton buttonAdd=new JButton("新增");
private JButton buttonDel=new JButton("删除");
public SampeDemo()
{
    JFrame frame=new JFrame("选择你的星座");
    cmb.addItem("--请选择--");    //向下拉列表中添加一项
    cmb.addItem("巨蟹座");
    cmb.addItem("狮子座");
    cmb.addItem("双鱼座");
    panel.add(cmb);
    panel.add(label);
    panel.add(jtf);
    panel.add(buttonAdd);
    panel.add(buttonDel);
    frame.add(panel);
    buttonAdd.addActionListener(new MyActionListener());    //“添加”按钮的事件
    buttonDel.addActionListener(new MyActionListener());    //“删除”按钮的事件
    cmb.addItemListener(new MyItemListener());    //下拉列表的事件
    frame.setBounds(300,200,600,200);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

上述程序创建的下拉列表为 cmb,调用它的 addItem() 方法向其中添加了两个选项。程序分别监听了按下“新增”按钮和“删除”按钮时的单击事件,以及从下拉列表中选择项时的选中事件。

(3) 创建 MyItemListener 类,实现 ItemListener 接口对选中事件进行处理,此时将选中项显示到文本框中。实现代码如下:

// 监听选中事件
class MyItemListener implements ItemListener
{
    @Override
    public void itemStateChanged(ItemEvent e)
    {
        String str=e.getItem().toString();
        panel.add(showInfo);
        showInfo.setText("您选择的星座是:"+str);
    }
}

(4) 创建 MyActionListener 类,实现 ActionListener 接口对按钮的单击事件进行处理。实现代码如下:

// 监听添加和删除按钮事件
class MyActionListener implements ActionListener
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        String command=e.getActionCommand();
        //添加按钮处理
        if(command.equals("新增"))
        {
            if(jtf.getText().length()!=0)
            {
                cmb.addItem(jtf.getText());    //添加项
                panel.add(showInfo);
                showInfo.setText("添加成功,新增了:"+jtf.getText());
            }
            else
            {
                panel.add(showInfo);
                showInfo.setText("请输入要添加星座");
            }
        }
        //删除按钮处理
        if(command.equals("删除"))
        {
            if(cmb.getSelectedIndex()!=-1)
            {
                //先获得要删除的项的值
                String strDel=cmb.getSelectedItem().toString();
                cmb.removeItem(strDel);    //删除项
                panel.add(showInfo);
                showInfo.setText("删除成功,删除了:"+strDel);
            }
            else
            {
                panel.add(showInfo);
                showInfo.setText("请选择要删除的星座");
            }
        }
    }
}

(5) 运行程序,在下拉列表中会出现 4 个选项,选择其中的“狮子座”项,此时显示效果如图 1 所示。

添加项

图1 添加项

(6) 从下拉列表中选择“狮子座”项,再单击“删除”按钮即可删除该项,如图 2 所示。

显示选中项

图2 显示选中项

(7) 在文本框中输入要添加的项并单击“新增”按钮,在下拉列表中将出现添加的项。图 3 所示为添加“处女座”后的效果。

删除项

图3 删除项

JSlider:滑块组件

滑块(JSlider)是一个允许用户在有限区间内通过移动滑块来选择值的组件。JSlider 类的常用构造方法如表 1 所示。

构造方法说明
JSlider()创建一个范围在 0~100 且初始值为 50 的水平滑块
JSlider(BoundedRangeModel brm)使用指定的 BoundedRangeModel 创建一个水平滑块
JSlider(int orientation)使用指定的方向创建一个滑块,范围在 0~100 且初始值为 50
JSlider(int min,int max)使用指定的最小值和最大值来创建一个水平滑块,初始值等于最小值加上最大值的平均值
JSlider(int min,int max,int value)用指定的最小值、最大值和初始值创建一个水平滑块

例如,创建一个最小值为 30,最大值为 120,初始值为 55 的水平滑块的语句如下所示。

JSIider slider=new JSIider(30,120,55);

滑块可以显示主刻度标记以及主刻度之间的次刻度标记。刻度标记之间的值的个数由 setMajorTickSpacing() 方法和 setMinorTickSpacing() 方法来控制。刻度标记的绘制由 setPaintTicks() 方法控制。

滑块也可以在固定时间间隔(或在任意位置)沿滑块刻度打印文本标签,标签的绘制由 setLabelTable() 方法和 setPaintLabels() 方法控制。

JSIider 类常用方法如表 2 所示。

方法名称说明
createStandardLabels(int increment)创建一个数字文本标签的 Hashtable,从滑块最小值处开始增加,并使用指定的增量
getLabelTable()返回哪些标签在哪些刻度绘制的字典
getMaj orTickSpacing()返回主刻度标记的间隔
getMaximum()从 BoundedRangeModel 返回滑块所支持的最大值
getMinimum()从 BoundedRangeModel 返回滑块所支持的最小值
getMinorTickSpacing()返回次刻度标记的间隔
getSnapToTicks()如果滑块(及其所表示的值)解析为最靠近用户放置滑块处的刻度标记的值,则返回为 true
getValue()从 BoundedRangeModel 返回滑块的当前值
setLabelTable(Dictionary labels)用于指定将在给定值处绘制哪个标签
setMaj orTickSpacing(int n)此方法设置主刻度标记的间隔
setMaximum(int maximum)将滑块的最大值设置为 maximum
setMinimum(int minimum)将滑块的最小值设置为 minimum
setMinorTickSpacing(int n)设置次刻度标记的间隔
setOrientation(int orientation)将滑块的方向设置为 SwingConstants.VERTICAL 或 SwingConstants.HORIZONTAL
setPaintLabels(boolean b)确定是否在滑块上绘制标签
setPaintTicks(boolean b)确定是否在滑块上绘制刻度标记
setPaintTrack(boolean b)确定是否在滑块上绘制滑道
setSnapToTicks(boolean b)指定为 true,则滑块(及其所表示的值)解析为最靠近用户放置滑块处的刻度标记的值
setValue(int n)将滑块的当前值设置为 n

例 1

在了解 JSIider 类的基础语法之后,下面创建一个滑块实例。实例非常简单,仅仅包含一个滑块,实例源代码如下所示。

package ch18;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JSlider;
public class JSliderDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("滑块组件示例");
        frame.setSize(100,100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container contentPane=frame.getContentPane();
        JSlider slider=new JSlider(0,100);
        slider.setMajorTickSpacing(10);
        slider.setMinorTickSpacing(5);
        slider.setPaintLabels(true);   
        slider.setPaintTicks(true);
        contentPane.add(slider);
        frame.setVisible(true);       
    }
}

上述代码首先创建一个 JFrame 窗口并进行必要属性设置,接着创建一个 JSIider 对象,设置最小值为 0,最大值为 100,然后设置滑块对象的刻度值。运行此时的实例程序,效果如图 1 所示。

无刻度和标签的滑块

图1 无刻度和标签的滑块

如果需要在滑块上添加刻度或标签,可以在“contentPane.add(slider);”前添加下面两行语句:

slider.setPaintLabels(true);
slider.setPaintTicks(true);

再次运行程序,此时滑块的运行效果如图 2 所示。

具有刻度和标签的滑块

图2 具有刻度和标签的滑块

JProgressBar:进度条组件

进度条(JProgressBar)是一种以可视化形式显示某些任务进度的组件。JProgressBar 类实现了一个用于为长时间的操作提供可视化指示器的 GUI 进度条。在任务的完成进度中,进度条显示该任务完成的百分比。此百分比通常由一个矩形以可视化形式表示,该矩形开始是空的,随着任务的完成逐渐被填充。此外,进度条可显示此百分比的文本表示形式。

JProgressBar 类的常用构造方法和 JSlider 类的常用构造方法一样,这里不再重复。如下示例代码演示了如何创建一个 JProgressBar 类实例。

//创建一个最小值是0,最大值是100的进度条
JProgressBar pgbar=new JProgressBar(0,100);
//创建一个最小值是0,最大值是60,当前值是20的进度条
JProgressBar pgbar=new JProgressBar(0,60,20);

JProgressBar 类的常用方法如表 1 所示。

方法名称说明
getMaximum()返回进度条的最大值
getMinimum()返回进度条的最小值
getPercentComplete()返回进度条的完成百分比
getString()返回当前进度的 String 表示形式
getValue()返回进度条的当前 value
setBorderPainted(boolean b)设置 borderPainted 属性,如果进度条应该绘制其边框,则此属性为 true
setIndeterminate(boolean newValue)设置进度条的 indeterminate 属性,该属性确定进度条处于确定模式中还 是处于不确定模式中
setMaximum(int n)将进度条的最大值设置为 n
setMinimum(int n)将进度条的最小值设置为 n
setOrientation(int newOrientation)将进度条的方向设置为 newOrientation
setString(String s)设置进度字符串的值
setStringPainted(boolean b)设置 stringPainted 属性的值,该属性确定进度条是否应该呈现进度字符串
setValue(int n)将进度条的当前值设置为 n
updateUI()将 UI 属性重置为当前外观对应的值

其中,setOrientation() 方法的参数值必须为 SwingConstants.VERTICAL 或 SwingConstants.HORIZONTAL。JProgressBar 使用 BoundedRangeModel 作为其数据模型,以 value 属性表示该任务的“当前”状态,minimum 和 maximum 属性分别表示开始点和结束点。

技巧:如果要执行一个未知长度的任务,可以调用 setlndeterminate(true) 将进度条设置为不确定模式。不确定模式的进度条将持续地显示动画来表示正进行的操作。一旦可以确定任务长度和进度量,则应该更新进度条的值,将其切换到确定模式。

例 1

使用 JProgressBar 类创建一个进度条模拟程序升级过程,实现过程如下。

(1) 创建一个继承自 JFrame 的 JProgressBarDemo 类。

(2) 在构造方法中添加一个空的进度条,然后设置它的显示属性。主要代码如下:

package ch18;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
public class JProgressBarDemo extends JFrame
{
    //static JProgressBarDemo frame;
    public JProgressBarDemo()
    {
        setTitle("使用进度条");
        JLabel label=new JLabel("欢迎使用在线升级功能!");
        //创建一个进度条
        JProgressBar progressBar=new JProgressBar();
        JButton button=new JButton("完成");
        button.setEnabled(false);
        Container container=getContentPane();
        container.setLayout(new GridLayout(3,1));
        JPanel panel1=new JPanel(new FlowLayout(FlowLayout.LEFT));
        JPanel panel2=new JPanel(new FlowLayout(FlowLayout.CENTER));
        JPanel panel3=new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel1.add(label);    //添加标签
        panel2.add(progressBar);    //添加进度条
        panel3.add(button);    //添加按钮
        container.add(panel1);
        container.add(panel2);
        container.add(panel3);
        progressBar.setStringPainted(true);
        //如果不需要进度上显示“升级进行中...”,可注释此行
        progressBar.setString("升级进行中...");
        //如果需要使用不确定模式,可使用此行
        //progressBar.setIndeterminate(true);
        //开启一个线程处理进度
        new Progress(progressBar, button).start();
        //单机“完成”按钮结束程序
        button.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                dispose();
                System.exit(0);
            }
        });
    }
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        // TODO Auto-generated method stub
        JProgressBarDemo frame=new JProgressBarDemo();
        //frame.setBounds(300,200,300,150);    //设置容器的大小
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
    }
}

(3) 创建 Progress 线程并实现对进度条进度的控制,实现代码如下。

private class Progress extends Thread
{
    JProgressBar progressBar;
    JButton button;
    //进度条上的数字
    int[] progressValues={6,18,27,39,51,66,81,100};
    Progress(JProgressBar progressBar,JButton button)
    {
        this.progressBar=progressBar;
        this.button=button;
    }
    public void run()
    {
        for(int i=0;i<progressValues.length;i++)
        {
            try
            {
                Thread.sleep(3000);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            //设置进度条的值
            progressBar.setValue(progressValues[i]);
        }
        progressBar.setIndeterminate(false);
        progressBar.setString("升级完成!");
        button.setEnabled(true);
    }
}
​

上述代码定义了一个进度条的进度数组 progressValues。线程每隔 1000 毫秒从数组中取一个数字作为当前进度,并使用 JProgressBar 类的 setValue() 方法更新到进度条。最后使进度条显示“升级完成!”字符串,并使“完成”按钮可用。

图 1 为程序的运行效果。图 2 为调用 Setlndeterminate(true) 方法后进度条使用不确定模式的运行效果。图 3 为默认的数字进度条运行效果。

进度条运行效果

进度条运行效果

图1 进度条运行效果

不确定模式下进度条的运行效果

图2 不确定模式进度条效果

数字模式下进度条的运行效果

图3 数字进度条运行效果

Timer:计时器组件

计时器(Timer)组件可以在指定时间间隔触发一个或多个 ActionEvent。设置计时器的过程包括创建一个 Timer 对象,在该对象上注册一个或多个动作侦听器,以及使用 start() 方法启动该计时器。

例如,以下代码创建并启动一个每秒(该时间由 Timer 构造方法的第一个参数指定)触发一次动作事件的计时器。Timer 构造方法的第二个参数指定接收计时器动作事件的监听器。

int delay=1000;    //时间间隔,单位为毫秒
ActionListener taskPerformer=new ActionListener()
{
    public void afrfcionPerformed(ActionEvent evt)
    {
        //具体的任务
    }
};
new Timer(delay,taskPerformer).start();

创建 Timer 类时要指定一个延迟参数和一个 ActionListener。延迟参数用于设置初始延迟和事件触发之间的延迟(以毫秒为单位)。启动计时器后,它将在向已注册监听器触发第一个 ActionEvent 之前等待初始延迟。第一个事件之后,每次超过事件间延迟时它都继续触发事件,直到被停止。

创建 Timer 类之后,可以单独更改初始延迟和事件间延迟,并且可以添加其他 ActionListener。如果希望计时器只在第一次时触发然后停止,可以对计时器调用 setRepeats(false)。Timer 类的常用方法如表 1 所示。

方法名称说明
addActionListener(ActionListener 1)将一个动作监听器添加到 Timer
getDelay()返回两次触发动作事件间延迟,以毫秒为单位
isCoalesce()如果 Timer 组合多个挂起的动作事件,则返回 true
isRunning()如果 Timer 正在运行,则返回 true
restart()重新启动 Timer,取消所有挂起的触发并使它按初始延迟触发
setCoalesce(boolean flag)设置 Timer 是否组合多个挂起的 ActionEvent
setDelay(int delay)设置 Timer 的事件间延迟,两次连续的动作事件之间的毫秒数
setLogTimers(boolean flag)启用/禁用计时器日志
setRepeats(boolean flag)如果 flag 为 false,则指示 Timer 只向其监听器发送一次动作事件
start()启动 Timer,使它开始向其监听器发送动作事件
stop()停止 Timer,使它停止向其监听器发送动作事件

例 1

编写一个实例,模拟软件安装过程中显示安装进度信息的进度条。该实例中使用 Timer 类模拟安装软件的实际过程,JProgressBar 类显示相应的进度信息,主要实现过程如下。

(1) 创建一个 JProgressBarDemo1 类并实现 ActionListener 接口和 ChangeListener 接口。

package ch18;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class JProgressBarDemo1 implements ActionListener,ChangeListener
{
    JFrame frame=null;
    JProgressBar progressbar;
    JLabel label;
    Timer timer;
    JButton b;
    public static void main(String[] agrs)
    {
        new JProgressBarDemo1();    //创建一个实例化对象
    }
}

(2) 在构造方法中对进度条和计时器进行设置。主要代码如下:

public JProgressBarDemo1()
{
    frame=new JFrame("软件安装");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container contentPane=frame.getContentPane();
    label=new JLabel(" ",JLabel.CENTER);    //创建显示进度信息的文本标签
    progressbar=new JProgressBar();    //创建一个进度条
    progressbar.setOrientation(JProgressBar.HORIZONTAL);
    progressbar.setMinimum(0);
    progressbar.setMaximum(100);
    progressbar.setValue(0);
    progressbar.setStringPainted(true);
    progressbar.addChangeListener(this);    //添加事件监听器
    //设置进度条的几何形状
    progressbar.setPreferredSize(new Dimension(300,20));
    progressbar.setBorderPainted(true);
    progressbar.setBackground(Color.pink);
    //添加启动按钮
    JPanel panel=new JPanel();
    b=new JButton("安装");
    b.setForeground(Color.blue);
    //添加事件监听器
    b.addActionListener(this);
    panel.add(b);
    timer=new Timer(100, this);    //创建一个计时器,计时间隔为100毫秒
    //把组件添加到frame中
    contentPane.add(panel,BorderLayout.NORTH);
    contentPane.add(progressbar,BorderLayout.CENTER);
    contentPane.add(label,BorderLayout.SOUTH);
    frame.pack();
    frame.setVisible(true);
}

(3) 实现 ActionListener 接口中的 actionPerformed() 方法,在这里控制计时器的开始,以及进度条值的变化。具体代码如下:

//实现事件监听器接口中的方法
public void actionPerformed(ActionEvent e)
{
    if(e.getSource()==b)
        timer.start();
    if(e.getSource()==timer)
    {
        int value=progressbar.getValue();
        if(value<100)
        {
            progressbar.setValue(++value);
        }
        else
        {
            timer.stop();
            frame.dispose();
        }
    }
}

(4) 实现 ChangeListener 接口中的 stateChange() 方法,具体代码如下:

public void stateChanged(ChangeEvent e1)    //实现事件监听器接口中的方法
{
    int value=progressbar.getValue();
    if(e1.getSource()==progressbar)
    {
        label.setText("目前已完成进度:"+Integer.toString(value)+" %");
        label.setForeground(Color.blue);
    }
}

(5) 运行程序,默认情况下进度条是 0%,如图 1 所示。

初始效果

图1 初始效果

单击“安装”按钮后进度会一直发生变化,如图 2 所示。

进度变化效果

图2 进度变化效果

JMenu和JPopupMenu:菜单和弹出式菜单

菜单由 Swing 中的 JMenu 类实现,可以包含多个菜单项和带分隔符的菜单。在菜单中,菜单项由 JMenuItem 类表示,分隔符由 JSeparator 类表示。

菜单本质上是带有关联 JPopupMenu 的按钮。当按下“按钮”时,就会显示 JPopupMenu。如果“按钮”位于 JMenuBar 上,则该菜单为顶层窗口。如果“按钮”是另一个菜单项,则 JPopupMenu 就是“下拉”菜单。

JMenu 类的常用方法

创建菜单常用构造方法有两个:JMenu() 和 JMenu(String s)。第一个构造方法创建一个无文本的 JMenu 对象,第二个构造方法创建一个带有指定文本的 JMenu 对象。JMenu 类的常用方法如表 1 所示。

方法名称说明
add(Action a)创建连接到指定 Action 对象的新菜单项,并将其追加到此菜单的末尾
add(Component c)将某个组件追加到此菜单的末尾
add(Component c,int index)将指定组件添加到此容器的给定位置
add(JMenuItem menultem)将某个菜单项追加到此菜单的末尾
add(String s)创建具有指定文本的新菜单项,并将其追加到此菜单的末尾
addSeparator()将新分隔符追加到菜单的末尾
doCliclc(int pressTime)以编程方式执行“单击”操作
getDelay()返回子菜单向上或向下弹出前建议的延迟(以毫秒为单位)
getltem(int pos)返回指定位置的 JMenuItem
getItemCount()返回菜单上的项数,包括分隔符
getMenuComponent(int n)返回位于位置 n 的组件
getMenuComponents()返回菜单子组件的 Component 数组
getSubElements()返回由 MenuElement 组成的数组,其中包含此菜单组件的子菜单
insert(JMenuItem mi,int pos)在给定位置插入指定的 JMenuitem
insert(String s,pos)在给定位置插入具有指定文本的新菜单项
insertSeparator(int index)在指定的位置插入分隔符
isMenuComponent(Component c)如果在子菜单层次结构中存在指定的组件,则返回 true
isPopupMenuVisible()如果菜单的弹出窗口可见,则返回 rue
isSelected()如果菜单是当前选择的(即高亮显示的)菜单,则返回 true
isTopLevelMenu()如果菜单是“顶层菜单”(即菜单栏的直接子级),则返回 true
setDelay(int d)设置菜单的 PopupMenu 向上或向下弹出前建议的延迟
setMenuLocation(int x,int y)设置弹出组件的位置
setPopupMenuVisible(boolean b)设置菜单弹出的可见性
setSelected(boolean b)设置菜单的选择状态

例 1

菜单如果依附到 JMenuBar 对象上,则此菜单就是菜单栏中的菜单。菜单如果依附在 JPopupMenu 对象上,此菜单就是弹出式菜单。实现菜单栏和弹出式菜单的原理是一样的,但在具体的实现方式上有一些区别。

下面编写一个案例,使用 JMenuBar 类创建一个包含“文件”菜单和“编辑”菜单的菜单窗口。主要实现代码如下:

package ch18;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
public class JMenuDemo1 extends JMenuBar
{
    public JMenuDemo1()
    {
        add(createFileMenu());    //添加“文件”菜单
        add(createEditMenu());    //添加“编辑”菜单
        setVisible(true);
    }
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("菜单栏");
        frame.setSize(300,200);
        frame.setJMenuBar(new JMenuDemo1());
        frame.setVisible(true);
    }
    //定义“文件”菜单
    private JMenu createFileMenu()
    {
        JMenu menu=new JMenu("文件(F)");
        menu.setMnemonic(KeyEvent.VK_F);    //设置快速访问符
        JMenuItem item=new JMenuItem("新建(N)",KeyEvent.VK_N);
        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,ActionEvent.CTRL_MASK));
        menu.add(item);
        item=new JMenuItem("打开(O)",KeyEvent.VK_O);
        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,ActionEvent.CTRL_MASK));
        menu.add(item);
        item=new JMenuItem("保存(S)",KeyEvent.VK_S);
        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,ActionEvent.CTRL_MASK));
        menu.add(item);
        menu.addSeparator();
        item=new JMenuItem("退出(E)",KeyEvent.VK_E);
        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,ActionEvent.CTRL_MASK));
        menu.add(item);
        return menu;
    }
    //定义“编辑”菜单
    private JMenu createEditMenu()
    {
        JMenu menu=new JMenu("编辑(E)");
        menu.setMnemonic(KeyEvent.VK_E);
        JMenuItem item=new JMenuItem("撤销(U)",KeyEvent.VK_U);
        item.setEnabled(false);
        menu.add(item);
        menu.addSeparator();
        item=new JMenuItem("剪贴(T)",KeyEvent.VK_T);
        menu.add(item);
        item=new JMenuItem("复制(C)",KeyEvent.VK_C);
        menu.add(item);
        menu.addSeparator();
        JCheckBoxMenuItem cbMenuItem=new JCheckBoxMenuItem("自动换行");
        menu.add(cbMenuItem);
        return menu;
    }

}

上述代码调用 JMenu 对象的 setMnemonic() 方法设置当前菜单的快速访问符。该符号必须对应键盘上的一个键,并且应该使用 java.awt.event.KeyEvent 中定义的 VK—XXX 键代码之一指定。

提示:快速访问符是一种快捷键,通常在按下 Alt 键和某个字母时激活。例如,常用的 Alt+F 是“文件” 菜单的快速访问符。

JMenuItem 类实现的是菜单中的菜单项。菜单项本质上是位于列表中的按钮。当用户单击“按钮”时,则执行与菜单项关联的操作。JMenuItem 的常用构造方法有以下三个。

  1. JMenuItem(String text):创建带有指定文本的 JMenuItem。

  2. JMenuItem(String text,Icon icon):创建带有指定文本和图标的 JMenuItem。

  3. JMenuItem(String text,int mnemonic):创建带有指定文本和键盘助记符的 JMenuItem。

在该实例中,创建菜单项后调用 JMenuItem 对象的 setAccelerator(KeyStroke) 方法来设置修改键,它能直接调用菜单项的操作监听器而不必显示菜单的层次结构。在本实例中没有实现事件监听机制,所以使用快捷键时将得不到程序的任何响应,但是在菜单项中将出现快捷键。

运行该实例,图 1 所示是“文件”菜单展开效果,图 2 所示是“编辑”菜单展开的效果。

“文件”菜单

图1 “文件”菜单

“编辑”菜单

图2 “编辑”菜单

弹出式菜单 JPopuMenu

弹出式菜单由 JPopupMenu 类实现,它是一个可弹出并显示一系列选项的小窗口。它还用于当用户选择菜单项并激活它时显示的“右拉式(pull-right)”菜单,可以在想让菜单显示的任何其他位置使用。例如,当用户在指定区域中右击时。

JPopupMenu 类的常用方法如表 2 所示。

方法名称说明
getInvoker()返回作为此弹出菜单的“调用者”的组件
setInvoker(Component invoker)设置弹出菜单的调用者,即弹出菜单在其中显示的组件
addPopupMenuListener(PopupMenuListener1)添加 PopupMenu 监听器
removePopupMenuListener(PopupMenuListener1)移除 PopupMenu 监听器
getPopupMenuListeners()返回利用 addPopupMenuListener()添加到此 JMenuitem 的所有 PopupMenuListener 组成的数组
getLabel()返回弹出菜单的标签
setLabel(String label)设置弹出菜单的标签
show(Component invoker,int x,int y)在调用者的坐标空间中的位置 X、Y 处显示弹出菜单
getComponentIndex(Component c)返回指定组件的索引

例 2

使用 JPopupMenu 类创建一个弹出式菜单,并在菜单中使用子菜单。主要实现代码如下:

package ch18;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
public class JPopupMenuDemo extends JFrame
{
    JMenu fileMenu;
    JPopupMenu jPopupMenuOne;
    JMenuItem openFile,closeFile,exit;
    JRadioButtonMenuItem copyFile,pasteFile;
    ButtonGroup buttonGroupOne;
    public JPopupMenuDemo()
    {
        jPopupMenuOne=new JPopupMenu();    //创建jPopupMenuOne对象
        buttonGroupOne=new ButtonGroup();
        //创建文件菜单及子菜单,并将子菜单添加到文件菜单中
        fileMenu=new JMenu("文件");
        openFile=new JMenuItem("打开");
        closeFile=new JMenuItem("关闭");
        fileMenu.add(openFile);
        fileMenu.add(closeFile);
        //将fileMenu菜单添加到弹出式菜单中
        jPopupMenuOne.add(fileMenu);
        //添加分割符
        jPopupMenuOne.addSeparator();
        //创建单选菜单项,并添加到ButtonGroup对象中
        copyFile=new JRadioButtonMenuItem("复制");
        pasteFile=new JRadioButtonMenuItem("粘贴");
        buttonGroupOne.add(copyFile);
        buttonGroupOne.add(pasteFile);
        //将copyFile添加到jPopupMenuOne中
        jPopupMenuOne.add(copyFile);
        //将pasteFile添加到jPopupMenuOne中
        jPopupMenuOne.add(pasteFile);
        jPopupMenuOne.addSeparator();
        exit=new JMenuItem("退出");
        //将exit添加到jPopupMenuOne中
        jPopupMenuOne.add(exit);
        //创建监听器对象
        MouseListener popupListener=new PopupListener(jPopupMenuOne);
        //向主窗口注册监听器
        this.addMouseListener(popupListener);
        this.setTitle("弹出式菜单");
        this.setBounds(100,100,250,150);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    public static void main(String args[])
    {
        new JPopupMenuDemo();
    }
    //添加内部类,其扩展了MouseAdapter类,用来处理鼠标事件
    class PopupListener extends MouseAdapter
    {
        JPopupMenu popupMenu;
        PopupListener(JPopupMenu popupMenu)
        {
            this.popupMenu=popupMenu;
        }
        public void mousePressed(MouseEvent e)
        {
            showPopupMenu(e);
        }
        public void mouseReleased(MouseEvent e)
        {
            showPopupMenu(e);
        }
        private void showPopupMenu(MouseEvent e)
        {
            if(e.isPopupTrigger())
            {
                //如果当前事件与鼠标事件相关,则弹出菜单
                popupMenu.show(e.getComponent(),e.getX(),e.getY());
            }
        }
    }
}

在使用弹出菜单时一定要注意层次关系和菜单的位置。程序运行后由于菜单没有被激活所以窗口是空白的,如图 1 所示。单击鼠标右键即可查看弹出式菜单,如图 2 所示。

img

图1 初始界面

弹出式菜单

图2 弹出式菜单

JToolBar:工具栏组件

工具栏提供了一个用来显示常用按钮和操作的组件。它可以把任意类型的组件附加到工具条上,但是通常是增加按钮。工具栏 JToolBar 类的常用构造方法如表 1 所示。

构造方法说明
JToolBar()创建新的工具栏,默认的方向为 HORIZONTAL
JToolBar(int orientation)创建具有指定 orientation 的新工具栏
JToolBar(String name)创建一个具有指定 name 的新工具栏
JToolBar(String name,int orientation)创建一个具有指定 name 和 orientation 的新工具栏

与 JMenuBar 不一样,JToolBar 对象可以直接被添加到容器中。JTodBar 类的常用方法如表 2 所示。

方法名称说明
add(Action a)添加一个指派动作的新的 JButton
addSeparator()将默认大小的分隔符添加到工具栏的末尾
addSeparator(Dimension size)将指定大小的分隔符添加到工具栏的末尾
getComponentAtIndex(int i)返回指定索引位置的组件
getComponentIndex(Component c)返回指定组件的索引
getMargin()返回工具栏边框和它的按钮之间的空白
getOrientation()返回工具栏的当前方向
isFloatable()获取 floatable 属性
isRollover()返回 rollover 状态
setBorderPainted(boolean b)设置 borderPainted 属性,如果需要绘制边框,则此属性为 true
setFloatable(boolean b)设置 floatable 属性,如果要移动工具栏,此属性必须设置为 true
setLayout(LayoutManager mgr)设置此容器的布局管理器
setMargin(Insets m)设置工具栏边框和它的按钮之间的空白
setOrientation(int o)设置工具栏的方向
setRollover(boolean rollover)设置此工具栏的 rollover 状态

例 1

下面通过实例来说明如何使用 JToolBar 创建工具栏,在该实例中给工具栏上的按钮添加了图片,当图片不存在时使用文字代替。主要实现步骤如下所示。

(1) 创建一个 ToolBarDemo 类,继承 JPanel 父类并实现 ActionListener 接口。

package ch18;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
public class ToolBarDemo extends JPanel implements ActionListener
{
    protected JTextArea textArea;
    protected String newline="\n";
    static final private String OPEN="OPEN";
    static final private String SAVE="SAVE";
    static final private String NEW="NEW";   
    //事件监听器部分的代码省略,请查阅源文件
    protected void displayResult(String actionDescription)
    {
        textArea.append(actionDescription+newline);
    }
    public static void main(String[] args)
    {
        JFrame.setDefaultLookAndFeelDecorated(true);
        //定义窗体
        JFrame frame=new JFrame("工具栏");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //定义面板
        ToolBarDemo newContentPane=new ToolBarDemo();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        //显示窗体
        frame.pack();
        frame.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent e)
    {
        // TODO 自动生成的方法存根
    }
}

(2) 在构造方法中对工具栏进行设置,主要代码如下所示。

public ToolBarDemo()
{
    super(new BorderLayout());
    //创建工具栏
    JToolBar toolBar=new JToolBar();
    addButtons(toolBar);
    //创建一个文本域,用来输出一些信息
    textArea=new JTextArea(15, 30);
    textArea.setEditable(false);
    JScrollPane scrollPane=new JScrollPane(textArea);
    //把组件添加到面板中
    setPreferredSize(new Dimension(450, 110));
    add(toolBar,BorderLayout.PAGE_START);
    add(scrollPane,BorderLayout.CENTER);
}

(3) 构造方法中创建了一个工具栏 toolBar,然后调用 addButtons() 方法为工具栏设置按钮。addButtons() 方法的代码如下:

protected void addButtons(JToolBar toolBar)
{
    JButton button=null;
    button=makeNavigationButton("new1",NEW,"新建一个文件","新建");
    toolBar.add(button);
    button=makeNavigationButton("open1",OPEN,"打开一个文件","打开");
    toolBar.add(button);
    button=makeNavigationButton("save1",SAVE,"保存当前文件","保存");
    toolBar.add(button);
}

(4) 在 addButtons() 方法中调用 makeNavigationButton() 方法,实现对工具栏上的按钮指定图片、动作指令、提示信息和无图片时的文本。具体实现代码如下:

protected JButton makeNavigationButton(String imageName,String actionCommand,String toolTipText,String altText)
{
    //搜索图片
    String imgLocation=imageName+".jpg";
    URL imageURL=ToolBarDemo.class.getResource(imgLocation);
    //初始化工具按钮
    JButton button=new JButton();
    //设置按钮的命令
    button.setActionCommand(actionCommand);
    //设置提示信息
    button.setToolTipText(toolTipText);
    button.addActionListener(this);
    if(imageURL!=null)
    {
        //找到图像
        button.setIcon(new ImageIcon(imageURL));
    }
    else
    {
        //没有图像
        button.setText(altText);
        System.err.println("Resource not found: "+imgLocation);
    }
    return button;
}

(5) 运行程序,在窗口的顶部会看到包含 3 个按钮的工具栏。当鼠标指针放在工具按钮上时出现提示信息,如图 1 所示。

img

图1 无图片工具栏

JFileChooser和JColorChooser:文件选择器和颜色选择器

文件选择器

文件选择器为用户能够操作系统文件提供了桥梁。swing 中使用 JFileChooser 类实现文件选择器,该类常用的构造方法如下。

  • JFileChooser():创建一个指向用户默认目录的 JFileChooser。

  • JFileChooser(File currentDirectory):使用指定 File 作为路径来创建 JFileChooser。

  • JFileChooser(String currentDirectoryPath):创建一个使用指定路径的 JFileChooser。

  • JFileChooser(String currentDirectoryPath, FileSystemView fsv):使用指定的当前目录路径和 FileSystem View 构造一个 JFileChooser。

JFileChooser 类的常用方法如下所示。

  • int showOpenDialog(Component parent):弹出打开文件对话框。

  • int showSaveDialog(Component parent):弹出保存文件对话框。

例 1

编写一个程序允许用户从本地磁盘中选择一个文件,并将选中的文件显示到界面。实现代码如下:

package ch18;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class JFileChooserDemo
{
    private JLabel label=new JLabel("所选文件路径:");
    private JTextField jtf=new JTextField(25);
    private JButton button=new JButton("浏览");
    public JFileChooserDemo()
    {
        JFrame jf=new JFrame("文件选择器");
        JPanel panel=new JPanel();
        panel.add(label);
        panel.add(jtf);
        panel.add(button);
        jf.add(panel);
        jf.pack();    //自动调整大小
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        button.addActionListener(new MyActionListener());    //监听按钮事件
    }
    //Action事件处理
    class MyActionListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent arg0)
        {
            JFileChooser fc=new JFileChooser("F:\\");
            int val=fc.showOpenDialog(null);    //文件打开对话框
            if(val==fc.APPROVE_OPTION)
            {
                //正常选择文件
                jtf.setText(fc.getSelectedFile().toString());
            }
            else
            {
                //未正常选择文件,如选择取消按钮
                jtf.setText("未选择文件");
            }
        }
    }
    public static void main(String[] args)
    {
        new JFileChooserDemo();
    }
}

在上述程序中使用内部类的形式创建了一个名称为 MyActionListener 的类,该类实现了 ActionListener 接口。其中 showOpenDialog() 方法将返回一个整数,可能取值情况有 3 种:JFileChooser.CANCEL—OPTION、JFileChooser.APPROVE_OPTION 和 JFileChooser.ERROR_OPTION,分别用于表示单击“取消”按钮退出对话框,无文件选取、正常选取文件和发生错误或者对话框已被解除而退出对话框。因此在文本选择器交互结束后,应进行判断是否从对话框中选择了文件,然后根据返回值情况进行处理。

运行程序,单击“浏览”按钮,会弹出选择文件的对话框,如果取消选择,此时会显示未选择文件;否则就会显示选择的文件路径及文件名称,如图 1 所示。

文件保存对话框

图1 文件选择对话框

使用 JFileChooser 对象调用 showSaveDialog() 方法会显示保存文件对话框,即将“int val=fc.showOpenDialog(null);”语句换成“int val=fc.showSaveDialog(null);”。在保存文件对话框中“保存”按钮对应的常量值是 JFileChooser.APPROVE_OPTION,“取消”按钮对应的常量值是JFileChooser.CANCEL_ OPTION。图 2 所示为文件保存对话框效果。

文件选择对话框

图2 文件保存对话框

颜色选择器

JColorChooser 类提供一个用于允许用户操作和选择颜色的控制器窗格。该类提供三个级别的 API

  1. 显示有模式颜色选取器对话框并返回用户所选颜色的静态便捷方法。

  2. 创建颜色选取器对话框的静态方法,可以指定当用户单击其中一个对话框按钮时要调用的 ActionListener。

  3. 能直接创建 JColorChooser 窗格的实例(在任何容器中),可以添加 PropertyChange 作为监听器以检测当前“颜色”属性的更改。

颜色选择器的常用构造方法如下。

  • JColorChooser():创建初始颜色为白色的颜色选取器窗格。

  • JColorChooser(Color initialColor):创建具有指定初始颜色的颜色选取器窗格。

  • JColorChooser(ColorSelectionModel model):创建具有指定 ColorSelectionModel 颜色选取器窗格。

一般使用 JColorChooser 类的静态方法 showDialog(Component component,String title,Color initialColor) 创建一个颜色对话框,在隐藏对话框之前一直堵塞进程。其中 component 参数指定对话框所依赖的组件,title 参数指定对话框的标题,initialColor 参数指定对话框返回的初始颜色,即对话框消失后返回的默认值。

JColorChooser 类的其他常用方法如表 1 所示。

方法名称说明
getColor()获取颜色选取器的当前颜色值
getDragEnabled()获取dragEnabled 属性的值
setColor(Color color)将颜色选取器的当前颜色设置为指定颜色
setColor(int c)将颜色选取器的当前颜色设置为指定颜色
setColor(int r,int g,int b)将颜色选取器的当前颜色设置为指定的 RGB 颜色
setDragEnabled(boolean b)设置 dragEnabled 属性,该属性必须为 true 才能启用对 此组件的自动拖动处理(拖放操作的第一部分)

例 2

创建一个示例演示如何使用 JColorChooser 类显示颜色选择器。示例代码非常简单,如下所示。

package ch18;
import java.awt.Color;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
public class JColorChooserDemo
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("颜色选择器");
        JColorChooser cc=new JColorChooser();
        cc.showDialog(frame,"颜色选择器",Color.white);
        //JColorChooser.showDialog(frame,"颜色选择器",Color.white);
        //设置窗口的关闭动作、标题、大小位置以及可见性等
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100,100,400,200);
        frame.setVisible(true);
    }
}

使用 JFrame 作为容器,在该容器内显示一个标题是“颜色选择器”、使用白色作为默认色的颜色选择器。运行后的颜色选择器窗口如图 3 所示。

颜色选择器

图3 颜色选择器

也可以不创建 JColorChooser 类实例,直接调用其 showDialog() 方法显示颜色选择器。即将如下代码

JFrame frame=new JFrame("颜色选择器");
JColorChooser cc=new JColorChooser();
cc.showDialog(frame,"颜色选择器",Color.white);

换成:

JColorChooser.showDialog(frame,"颜色选择器",Color.white);

JOptionPane:对话框组件

对话框通常用作从用户处接收附加信息,或者提供发生了某种事件的通知。Java 提供了 JOptionPane 类,用来创建标准对话框,也可以通过扩展 JDialog 类创建自定义的对话框。JOptionPane 类可以用来创建 4 种类型的标准对话框:确认对话框、消息对话框、输入对话框和选项对话框。

确认对话框

确认对话框显示消息,并等待用户单击“确定”按钮来取消对话框,该对话框不返回任何值。而确认对话框询问一个问题,需要用户单击合适的按钮做出响应。确认对话框返回对应被选按钮的值。

创建确认对话框的方法如下:

public static int showConfirmDialog(Component parentComponent,Object message,String title,int optionType,int messageType,Icon icon)

参数 parentComponent、message、title、messageType 和 icon 与 showMessageDialog() 方法中的参数的含义相同。其中,只有 parentComponent 和 message 参数是必需的,title 的默认值为“选择一个选项”。messageType 的默认值是 QUESTION_MESSAGE。optionType 参数用于控制在对话框上显示的按钮,可选值如下:

  • 0 或 JOptionPane.YES_NO_OPTIION。

  • 1 或 JOptionPane.YES_NO_CANCEL_0PTII0N。

  • 2 或 JOptionPane.OK_CANCEL_OPTIION。

例如,使用 showCon&mDialog() 方法创建 3 个确认对话框,该方法中指定的参数个数和参数值都是不同的,语句如下:

JOptionPane.showConfirmDialog(p,"确定要删除吗?","删除提示",0);
JOptionPane.showConfirmDialog(p,"确定要删除吗?","删除提示",1,2);
ImageIcon icon=new ImageIcon("F:\\pic\\n63.gif");
JOptionPane.showConfirmDialog(p,"确定要删除吗?","删除提示",2,1,icon);

这 3 条语句所实现的对话框分别如图 1 所示。

确认对话框

确认对话框

确认对话框

图1 确认对话框

showConfirmDialog() 方法返回所选选项对应的值,这些值可以是整数或常量值,如下:

  • 0 或 JOptionPane.YES_OPTIION。

  • 1 或 JOptionPane.NO_OPTIION。

  • 2 或 JOptionPane.CANCEL_OPTIION。

  • 0 或 JOptionPane.OK_OPTIION。

  • -1 或 JOptionPane.CLOSED_OPTIION。

提示:除了 CLOSED_OPTIION 外,其他常量值都对应于激活的按钮。CLOSED_OPTIION 表示对话框在没有任何按钮激活的情况下关闭,例如单击对话框上的关闭图标按钮。

消息对话框

消息对话框显示一条提示或警告用户的信息,并等待用户单击 OK 或“确定”按钮以关闭对话框。创建消息对话框的方法如下:

public static void showMessageDialog(Component parentComponent,Object message,String title,int messageType,Icon icon)

其中,只有 parentComponent 参数和 message 参数是必须指定的。parentComponent 可以是任意组件或者为空;message 用来定义提示信息,它是一个对象,但是通常使用字符串表示;title 是设置对话框标题的字符串;messageType 是以下整型或常量中的一个。

  • 0 或 JOptionPane.ERROR_MESSAGE。

  • 1 或 JOptionPane.INFORMATION_MESSAGE。

  • JOptionPane.PLAIN_MESSAGE。

  • 2 或 JOptionPane.WARNING_MESSAGE。

  • 3 或 JOptionPane.QUESTION_MESSAGE。

默认情况下,messageType 的值是 JOptionPane.INFORMATION_MESSAGE。除类型 PLAIN_MESSAGE外,每种类型都有相应的图标,也可以通过 icon 参数提供自己的图标。

例如,下面的代码演示了不同的 messageType 取值实现的效果。

JOptionPane.showMessageDialog(p,"用户名或密码错误!","错误 ",0);
JOptionPane.showMessageDialog(p,"请注册或登录...","提示",1);
JOptionPane.showMessageDialog(p,"普通会员无权执行删除操作!","警告",2);
JOptionPane.showMessageDialog(p,"你是哪一位?请输入用户名","问题",3);
JOptionPane.showMessageDialog(p,"扫描完毕,没有发现病毒!","提示",JOptionPane.PLAIN_MESSAGE);

第一行语句表示创建一个错误对话框。第二行语句表示创建一个提示对话框。第三行语句表示创建一个警告对话框。第四行语句表示创建一个问题对话框。第五行语句表示创建一个无图标对话框。这 5 条语句创建的对话框效果分别如图 2 所示。

不同类型的消息对话框

不同类型的消息对话框

不同类型的消息对话框

不同类型的消息对话框

不同类型的消息对话框

图2 不同类型的消息对话框

输入对话框

输入对话框用于接收用户的输入。输入组件可以由文本框、下拉列表或者列表框进行实现。如果没有指定可选值,那么就使用文本框接收输入;如果指定了一组可选值,可选值的个数小于 20,那么将使用下拉列表显示;如果可选值的个数大于或等于 20,那么这些可选值将通过列表框显示。

创建输入对话框的方法如下:

public static String showInputDialog(Component parentComponent,Object message,String title,int messageType)
public static Object showInputDSalog(Component parentComponent,Object message,String title,int messageType,Icon icon,Object[] selectionValue,Object initValue)

其中,第一个 showInputDialog() 方法用于使用文本框输入,第二个 showInputDialog() 方法用于下拉列表或列表框的显示方式。参数 parentComponent 是必需的,message 默认为空,title 默认值为“输入”,messageType 的值默认为 3 或 JOptionPane.QUESTION_MESSAGE。

例如,使用 showInputDialog() 方法创建两个输入文本框,语句如下:

JOptionPane.showInputDialog(panel,"请输入用户名","输入用户名",1);
String[] str={"admin","maxianglin","calcl23456","adminl23"};
JOptionPane.showInputDialog(panel,"请选择用户名","选择用户名",1,null,str,str[0]);

第一个对话框没有指定列表值,那么将显示文本框;第二个对话框值显示为下拉列表的形式,如图 3 所示。

输入对话框

输入对话框

图3 输入对话框

提示:showInputDialog() 方法中没有 optionType 参数,表示输入对话框的按钮是不可以设置的,通常显示“确定”和“取消”按钮。

选项对话框

选项对话框允许用户自己定制按钮内容。创建选项对话框的方法如下:

public static int showOptionDialog(Component parentComponent,Object message,String title,int optionType,int messageType,icon icon,Object[] options,Object initValue)

其中,使用 options 参数指定按钮,initValue 参数用于指定默认获得焦点的按钮。该方法返回表明激活的按钮的一个整型值。

例如,创建一个 JButton 按钮数组,然后使用 showOptionDialog() 方法创建一个选项对话框,根据这个 JButton 数组来显示对话框的按钮,如下:

JButton[] bs={new JButton("确定"),new JButton("取消"),new JButton("重置")};
JOptionPane.showOptionDialog(panel,"请选择其中的一项:","选择",1,3,null,bs,bs[0]);

显示效果如图 4 所示。

“选择”对话框

图4 “选择”对话框

JTable:表格

表格是 Swing 新增加的组件,主要功能是把数据以二维表格的形式显示出来,并且允许用户对表格中的数据进行编辑。表格组件是最复杂的组件之一,它的表格模型功能非常强大、灵活而易于执行。由于篇幅有限,本节只介绍默认的表格模型。

Swing 使用 JTable 类实现表格,常用构造方法如下所示。

  • JTable():构造一个默认的 JTable,使用默认的数据模型、默认的列模型和默认的选择模型对其进行初始化。

  • JTable(int numRows,int numColumns):使用 DefaultTableModel 构造具有 numRows 行和 numColumns 列个空单元格的 JTable。

  • JTable(Object rowData,Object[] columnNames):构造一个 JTable 来显示二 维数组 rowData 中的值,其列名称为 columnNames。

创建一个带有滚动条的 JTable 对象非常简单,如下所示。

JTable table=new JTable(5,6);
JScrollPane pane=new JScrollPane(table);

第一条语句创建了一个 JTable 对象。第二条语句创建了一个存放 JTable 对象的 JScrollPane 对象,该对象是一个视图对象。JScrollPane是一个垂直和水平滚动条,以及可设置行和列标题的容器。上面两行代码执行后的表格效果如图1 所示。

表格

图1 表格

表格有很多的选项设置,因此 JTable 类常用方法也很多,这些常用方法如表 1 所示。

方法名称说明
getColumnCount()返回列模型中的列数
getColumnN ame(int column)返回出现在视图中 column 列位置处的列名称
getRowCount()返回 JTable 中可以显示的行数(给定无限空间)
getRowSorter()返回负责排序的对象
getSelectedColumn()返回第一个选定列的索引,如果没有选定的列, 则返回 -1
getSelectedRow()返回第一个选定行的索引,如果没有选定的行, 则返回 -1
getValueAt(int row,int column)返回 row 和 column 位置的单元格值
isEditing()如果正在编辑单元格,则返回 true
selectAll()选择表中的所有行、列和单元格
setColumnSelectionInterval(int index0,int index1)选择从 index0 到 index1之间(包含两端)的列
setRowSelectionInterval(int index0,int index1)选择从 index0 到 index1 之间(包含两端)的行
setTableHeader(JTableHeader tableHeader)将此 JTable 所使用的 tableHeader 设置为 newHeader
setUpdateSelectionOnSort(boolean update)指定排序后是否应该更新选择
setValueAt(Object a Value,int row,int column)设置表模型中 row 和 column 位置的单元格值

例 1

使用 JTable 类创建一个包含 8 列的学生成绩表,并向表格中填充几行数据,具体实现代码如下所示。

package ch18;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class JTableDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("学生成绩表");
        frame.setSize(500,200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container contentPane=frame.getContentPane();
        Object[][] tableDate=new Object[5][8];
        for(int i=0;i<5;i++)
        {
            tableDate[i][0]="1000"+i;
            for(int j=1;j<8;j++)
            {
                tableDate[i][j]=0;
            }
        }
        String[] name={"学号","软件工程","Java","网络","数据结构","数据库","总成绩","平均成绩"};
        JTable table=new JTable(tableDate,name);
        contentPane.add(new JScrollPane(table));
        frame.setVisible(true);
    }
}

如上述代码所示,表格组件和其他组件类似,可以方便地创建一个 JTable 对象。 如果 JTbale 对象直接添加到 JFrame 中,则表头显示不出来,需要把表格对象放入 JScrollPane 对象中,之后把 JScrollPane 对象添加到 JFrame 中。实例的运行效果如图 2 所示。

学生成绩表运行效果

图2 学生成绩表运行效果

例 2

Swing 中表格的数据可以根据需求动态变化,比如对于表格中不需要的数据,可以将其删除。本实例将演示如何从表格中删除用户选择的行,实现过程如下。

(1) 创建一个继承自 JFrame 的 RowDeleteDemo 类。

package ch18;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
public class RowDeleteDemo extends JFrame
{
    private JPanel contentPane;
    private JTable table;
    /**
     * Launch the application.
     */
    public static void main(String[] args)
    {
        RowDeleteDemo frame = new RowDeleteDemo();
        frame.setVisible(true);
    }
    /**
     * Create the frame.
     */
}

(2) 在构造方法中增加表格,设置表格的数据模型,添加“删除”按钮并监听单击事件。实现代码如下:

public RowDeleteDemo()
{
    addWindowListener(new WindowAdapter()
    {
        @Override
        public void windowActivated(WindowEvent e)
        {
            do_this_windowActivated(e);
        }
    });
    setTitle("图书信息表");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100,100,450,200);
    contentPane=new JPanel();
    contentPane.setBorder(new EmptyBorder(5,5,5,5));
    contentPane.setLayout(new BorderLayout(0,0));
    setContentPane(contentPane);
    JPanel panel=new JPanel();
    contentPane.add(panel,BorderLayout.SOUTH);
    JButton button=new JButton("删除");
    button.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            do_button_actionPerformed(e);
        }
    });
    panel.add(button);
    JScrollPane scrollPane=new JScrollPane();
    contentPane.add(scrollPane,BorderLayout.CENTER);
    table=new JTable();
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    scrollPane.setViewportView(table);
}

(3) 监听窗体激活事件,完成向表中增加数据的功能。这里使用了表格模型对象,它可以方便地处理表格中的数据。实现代码如下:

protected void do_this_windowActivated(WindowEvent e)
{
    DefaultTableModel tableModel=(DefaultTableModel) table.getModel();    //获得表格模型
    tableModel.setRowCount(0);    //清空表格中的数据
    tableModel.setColumnIdentifiers(new Object[]{"书名","出版社","出版时间","丛书类别","定价"});    //设置表头
    tableModel.addRow(new Object[]{"Java从入门到精通(第2版)","清华大学出版社","2010-07-01","软件工程师入门丛书","59.8元"});    //增加列
    tableModel.addRow(new Object[]{"PHP从入门到精通(第2版)","清华大学出版社","2010-07-01","软件工程师入门丛书","69.8元"});
    tableModel.addRow(new Object[]{"Visual Basic从入门到精通(第2版)","清华大学出版社","2010-07-01","软件工程师入门丛书","69.8元"});
    tableModel.addRow(new Object[]{"Visual C++从入门到精通(第2版)","清华大学出版社","2010-07-01","软件工程师入门丛书","69.8元" });
    table.setRowHeight(30);
    table.setModel(tableModel);    //应用表格模型
}

(4) 监听用户单击“删除”按钮事件,这里通过 do_button_actionPerformed() 方法完成。在该方法中,首先获取表格模型,然后获得用户选择的行,再执行删除数据操作。实现代码如下:

protected void do_button_actionPerformed(ActionEvent e)
{
    DefaultTableModel model=(DefaultTableModel) table.getModel();    //获得表格模型
    int[] selectedRows=table.getSelectedRows();
    for(int i=selectedRows[0];i<selectedRows.length;i++)
    {
        model.removeRow(selectedRows[0]);
    }
    table.setModel(model);
}

(5) 运行程序,默认在表格中会显示所有数据,如图 3 所示。图 4 所示为删除两行后的表格效果。

删除前表格数据

图3 删除前表格数据

删除后表格数据

图4 删除后表格数据

JTree:树组件

如果要显示一个层次关系分明的一组数据,用树结构是最合适的。树如同 Windows 资源管理器的左半部,可通过单击文件夹展开或者收缩内容。

Swing 使用 JTree 类实现树,它的主要功能是把数据按照树状进行显示,其数据来源于其他对象。JTree 树中最基本的对象叫作节点,表示在给定层次结构中的数据项。树以垂直方式显示数据,每行显示一个节点。树中只有一个根节点,所有其他节点从这里引出。除根节点外,其他节点分为两类:一类是代子节点的分支节点,另一类是不带子节点的叶节点。

JTree 类的常用构造方法如下表所示。

构造方法说明
JTree()返回带有示例模型的 JTree
JTree(Object[] value)返回 JTree,指定数组的每个元素作为不被显示的新根节点的子节点
JTree(TreeNode root)返回 JTree,使用指定的 root 作为其根节点
JTree(TreeNode root,boolean aslcsAllowsChildren)返回 JTree,使用指定的 root 作为其根节点,asksAllowsChildren 用 于确定节点是否为叶节点

树节点由 javax.swing.tree 包中的接口 TreeNode 定义,该接口被 DefaultMutableTreeNode 类实现。

为了创建一个树,使用 DefaultMutableTreeNode 类为树创建节点,它的两个常用的构造方法如下。

  1. DefaultMutableTreeNode(Object userObject):创建没有父节点和子节点,但允许有子节点的树节点,并使用指定的用户对象对它进行初始化。

  2. DefaultMutableTreeNode(Object userObject,boolean allowsChildren):创建没有父节点和子节点的树节点,使用指定的用户对象对它进行初始化,仅在指定时才允许有子节点。

例 1

节点是树结构中最主要的元素,因此对节点操作是树结构最重要的操作。下面这个实例将介绍如何使用树 JTree 对象和节点对象创建简单的树型界面。该实例代码如下:

package ch18;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class JTreeDemo
{
    public static void main(String[] agrs)
    {
        JFrame frame=new JFrame("教师学历信息");
        frame.setSize(330,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JTreeDemo().createComponent());
        frame.pack();
        frame.setVisible(true);
    }
    private JPanel createComponent()
    {
        JPanel panel=new JPanel();
        DefaultMutableTreeNode root=new DefaultMutableTreeNode("教师学历信息");
        String Teachers[][]=new String[3][];
        Teachers[0]=new String[]{"王鹏","李曼","韩小国","穆保龄","尚凌云","范超峰"};
        Teachers[1]=new String[]{"胡会强","张春辉","宋芳","阳芳","朱山根","张茜","宋媛媛"};
        Teachers[2]=new String[]{"刘丹","张小芳","刘华亮","聂来","吴琼"};
        String gradeNames[]={"硕士学历","博士学历","博士后学历"};
        DefaultMutableTreeNode node=null;
        DefaultMutableTreeNode childNode=null;
        int length=0;
        for(int i=0;i<3;i++)
        {
            length=Teachers[i].length;
            node=new DefaultMutableTreeNode(gradeNames[i]);
            for (int j=0;j<length;j++)
            {
                childNode=new DefaultMutableTreeNode(Teachers[i][j]);
                node.add(childNode);
            }
            root.add(node);
        }
        JTree tree=new JTree(root);
        panel.add(tree);
        panel.setVisible(true);
        return panel;
    }
}

在该实例中,创建树型界面的具体工作是由 createComponent() 私有方法完成的。在该方法中,首先创建一个根节点 root,接着定义两个数组来存放节点中的文本信息,然后通过嵌套 for 循环语句来创建除根节点外的所有节点并添加到对应的父节点上。最后把这些父节点添加到根节点中,该实例的运行效果如图 1 所示。

教师学历信息运行效果

图1 教师学历信息运行效果

JTabbedPane:选项卡组件

使用选项卡可以在有限的布局空间内展示更多的内容。Swing 使用 JTabbedPane 类实现选项卡。

JTabbedPane 类创建的选项卡可以通过单击标题或者图标在选项卡之间进行切换。JTabbedPane 类的常用构造方法如下所示。

  • JTabbedPane():创建一个具有默认 JTabbedPane.TOP 布局的空 TabbedPane。

  • JTabbedPane(int tabPlacement):创建一个空的 TabbedPane,使其具有以下指定选项卡布局中的一种:JTabbedPane.TOP、JTabbedPane.BOTTOM、JTabbedPane.LEFT 或 JTabbedPane.RIGHT。

创建了 JTabbedPane 实例之后,可使用 addTab() 方法和 insertTab() 方法将选项卡/组件添加到 TabbedPane 对象中。选项卡通过对应于添加位置的索引来表示,其中第一个选项卡的索引为 0,最后一个选项卡的索引为选项卡数量减 1。

TabbedPane 使用 SingleSelectionModel 属性来表示选项卡索引集和当前所选择的索引。如果选项卡数量大于 0,则总会有一个被选定的索引,此索引默认被初始化为第一个选项卡;如果选项卡数量为 0,则所选择的索引为 -1。

JTabbedPane类的常用方法如表 1 所示。

方法名称说明
add(Component component,int index)在指定的选项卡索引位置添加一个 component,默认的选项卡 标题为组件名称
addTab(String title, Component component)添加一个使用 title 作为标题,且没有图标的组件
getComponentAt(int index)返回 index 位置的组件
getSelectedComponent()返回此选项卡窗格当前选择的组件
getSelectedIndex()返回当前选择的此选项卡窗格的索引
getTabCount()返回此 tabbedPane 的选项卡数
insertTab(String title,Icon icon,Component component, String tip,int index)在 index 位置插入一个组件,该组件通过 title 或 icon(任意一个 都可以为 null)来表示
isEnabledAt(int index)返回当前是否启用了 index 位置的选项卡
remove(int index)移除对应于指定索引的选项卡和组件
setEnabledAt(int index,boolean enabled)设置是否启用 index 位置的选项卡
setMnemonicAt(int tablndex,int mnemonic)设置用于访问指定选项卡的键盘助记符
setTitleAt(int index,String title)将 index 位置的标题设置为 title,它可以为 null
setToolTipTextAt(int index,String toolTipText)将 index 位置的工具提示文本设置为 toolTipText,它可以为 null

选项卡面板和卡片布局不同的是,选项卡面板可以有标签。下面的示例代码创建了一个选项卡面板,并在选项卡面板中添加了一个 JPand 面板。

JTabbedPane tabbedPane=new JTabbedPane();
ImageIcon icon=new ImageIcon("temp.gif");
JComponent panel1=makeTextPanel("Panel#1");    //创建一个jPanel容器,容纳其他组件
tabbedPane.addTab("Tab 1",icon,panel1,"Does nothing");
tabbedPane.setMnemonicAt(0,KeyEvent.VK_1);    //设置快捷键

该代码段中的第三条语句向选项卡面板 tabbedPane 中添加了一个 panel1 组件(该组件是一个 JPanel 对象),该方法中的第一个参数是选项卡标签文本;第二个参数是 Icon 对象,它作为选项卡标签上的图标;第三个参数是添加到选项卡上的组件;第四个参数是当鼠标指针放在选项卡标签上时出现的提示信息。

例 1

使用 JTabbedPane 类创建一个包含 4 个标签的选项卡面板,并分别为每个选项卡填充内容,主要实现过程如下。

(1) 创建一个 TabbedPaneDemo 类并继承 JPanel 父类。

package ch18;
import javax.swing.JPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
public class TabbedPaneDemo extends JPanel
{
    public static void main(String[] args)
    {
        JFrame frame=new JFrame("我的电脑 - 属性");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TabbedPaneDemo(),BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }
}

(2) 在构造方法中创建空白选项卡,新建标签,指定标签的文本和图片,以及标签对应的内容面板和快捷访问符。这些代码如下:

public TabbedPaneDemo()
{
    super(new GridLayout(1,1));
    JTabbedPane tabbedPane=new JTabbedPane();
    ImageIcon icon=createImageIcon("tab.jp1g");
    JComponent panel1=makeTextPanel("计算机名");
    tabbedPane.addTab("计算机名",icon, panel1,"Does nothing");
    tabbedPane.setMnemonicAt(0,KeyEvent.VK_1);
    JComponent panel2=makeTextPanel("硬件");
    tabbedPane.addTab("硬件",icon,panel2,"Does twice as much nothing");
    tabbedPane.setMnemonicAt(1,KeyEvent.VK_2);
    JComponent panel3=makeTextPanel("高级");
    tabbedPane.addTab("高级",icon,panel3,"Still does nothing");
    tabbedPane.setMnemonicAt(2,KeyEvent.VK_3);
    JComponent panel4=makeTextPanel("系统保护");
    panel4.setPreferredSize(new Dimension(410,50));
    tabbedPane.addTab("系统保护",icon,panel4,"Does nothing at all");
    tabbedPane.setMnemonicAt(3,KeyEvent.VK_4);
    add(tabbedPane);
}

(3) 编写 makeTextPane() 方法的实现,该方法主要用于创建一个内容面板,并在面板上添加指定的文本内容,具体实现代码如下所示。

protected JComponent makeTextPanel(String text)
{
    JPanel panel=new JPanel(false);
    JLabel filler=new JLabel(text);
    filler.setHorizontalAlignment(JLabel.CENTER);
    panel.setLayout(new GridLayout(1,1));
    panel.add(filler);
    return panel;
}

(4) 构造方法中用到的 createImageIcon() 方法主要用于加载图片,如果图片不存在则返回 null。

protected static ImageIcon createImageIcon(String path)
{
    java.net.URL imgURL=TabbedPaneDemo.class.getResource(path);
    if(imgURL!=null)
    {
        return new ImageIcon(imgURL);
    }
    else
    {
        System.err.println("Couldn't find file: "+path);
        return null;
    }
}

(5) 运行程序,结果如图 1 所示。假设存在构造方法中指定的图片,那么在图 1 所示的运行效果中,每个单击选项卡标签前都带有各自的图标。

文本选项卡面板

图1 文本选项卡面板

文本编辑器的实现

最简单的文本编辑器要数 Windows 的记事本了。在学习了本章知识之后,本次案例将完成一个简单的文本编辑器程序。它可以打开文本文件,并输出文本文件的位置和内容。其中用到了菜单工具栏以及选项卡等组件,是一个综合类的应用,主要实现步骤如下。

(1) 创建一个 TextFileOpener 类并继承 JFrame 父类。

package ch18;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.filechooser.FileNameExtensionFilter;
public class TextFileOpener extends JFrame
{
    private static final long serialVersionUID=-9077023825514749548L;
    private JTextArea ta_showText;    //定义显示文件属性的文本域
    private JTextArea ta_showProperty;    //定义显示文件内容的文本域
    //Launch the application.
    public static void main(String[] args)
    {
        TextFileOpener frame=new TextFileOpener();
        frame.setVisible(true);
    }   
}

(2) 在构造方法中布局的设置,包括窗口大小、菜单栏和菜单项、工具栏,以及对各个组件的事件监听,主要实现代码如下所示。

public TextFileOpener()
{
    setTitle("文本编辑器");    //设置窗体标题
    setBounds(100,100,400,250);    //设置窗体位置和大小
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);    //设置窗体默认关闭方式
    final JMenuBar menuBar=new JMenuBar();    //创建菜单栏
    setJMenuBar(menuBar);    //把菜单栏放到窗体上
    final JMenu mn_file=new JMenu();    //创建文件菜单
    mn_file.setText("文件");    //为文件菜单设置标题
    menuBar.add(mn_file);    //把文件菜单添加到菜单栏上
    final JMenuItem mi_open=new JMenuItem();    //创建打开菜单项
    mi_open.addActionListener(new ActionListener()
    {
        //为打开菜单项添加监听器
        public void actionPerformed(final ActionEvent arg0)
        {
            openTextFile();    //调用方法,操作文件
        }
    });
    mi_open.setText("打开");    //设置打开菜单项的标题
    mn_file.add(mi_open);    //把打开菜单项添加到文件菜单
    mn_file.addSeparator();    //添加菜单分隔符
    final JMenuItem mi_exit=new JMenuItem();    //创建退出菜单项
    mi_exit.addActionListener(new ActionListener()
    {
        //为退出菜单项添加监听器
        public void actionPerformed(final ActionEvent arg0)
        {
            System.exit(0);    //退出系统
        }
    });
    mi_exit.setText("退出");    //设置退出菜单项的标题
    mn_file.add(mi_exit);    //把退出菜单项添加到文件菜单
    final JMenu mn_edit=new JMenu();    //创建编辑菜单
    mn_edit.setText("编辑");    //为编辑菜单设置标题
    menuBar.add(mn_edit);    //把编辑菜单添加到菜单栏上
    final JMenuItem mi_copy=new JMenuItem();    //创建复制菜单项
    mi_copy.setText("复制");    //设置复制菜单项的标题
    mn_edit.add(mi_copy);    //把复制菜单项添加到编辑菜单
    final JMenuItem mi_cut=new JMenuItem();    //创建剪切菜单项
    mi_cut.setText("剪切");    //设置剪切菜单项的标题
    mn_edit.add(mi_cut);    //把剪切菜单项添加到编辑菜单
    final JMenuItem mi_paste=new JMenuItem();    //创建粘贴菜单项
    mi_paste.setText("粘贴");    //设置粘贴菜单项的标题
    mn_edit.add(mi_paste);    //把粘贴菜单项添加到编辑菜单
    final JToolBar toolBar=new JToolBar();    //创建工具栏
    getContentPane().add(toolBar,BorderLayout.NORTH);    //把工具栏放到窗体上方
    final JButton btn_open=new JButton();    //创建工具按钮
    btn_open.addActionListener(new ActionListener()
    {
        //添加动作监听器
        public void actionPerformed(final ActionEvent arg0)
        {
            openTextFile();    //调用方法,操作文件
        }
    });
    btn_open.setText("  打  开  ");    //设置工具按钮的标题
    toolBar.add(btn_open);    //把工具按钮添加到工具栏上
    final JButton btn_exit=new JButton();    //创建工具按钮
    btn_exit.addActionListener(new ActionListener()
    {
        //添加动作监听器
        public void actionPerformed(final ActionEvent arg0)
        {
            System.exit(0);    //退出系统
        }
    });
    btn_exit.setText("  退  出  ");    //设置工具按钮的标题
    toolBar.add(btn_exit);    //把工具按钮添加到工具栏上
    final JTabbedPane tabbedPane=new JTabbedPane();    //创建选项卡面板
    getContentPane().add(tabbedPane,BorderLayout.CENTER);    //把选项卡面板放到窗体中央
    final JScrollPane scrollPane1=new JScrollPane();    //创建滚动面板
    //把滚动面板放到选项卡的第一个选项页
    tabbedPane.addTab("文件的属性",null,scrollPane1,null);
    ta_showProperty=new JTextArea();    //创建文本域
    //把文本域添加到滚动面板的视图中
    scrollPane1.setViewportView(ta_showProperty);
    final JScrollPane scrollPane2=new JScrollPane();    //创建滚动面板
    //把滚动面板放到选项卡的第二个选项页
    tabbedPane.addTab("文件的内容",null,scrollPane2,null);
    ta_showText=new JTextArea();    //创建文本域
    //把文本域添加到滚动面板的视图中
    scrollPane2.setViewportView(ta_showText);
}

(3) 无论是从菜单栏还是工具栏选择“打开”文件操作时都是调用 openTextFile() 方法。该方法会弹出文件选择器让用户选择一个文件,然后使用文件流获取文件属性和读取文件的内容,再把信息呈现到界面上。openTextFile() 方法的实现代码如下:

//用于打开文件并获得文件信息的方法
public void openTextFile()
{
    JFileChooser fileChooser=new JFileChooser();    //创建文件选择对话框
    fileChooser.setFileFilter(new FileNameExtensionFilter("文本文件","txt"));
    int returnValue=fileChooser.showOpenDialog(getContentPane());    //打开文件选择对话框
    if(returnValue==JFileChooser.APPROVE_OPTION)
    {
        //判断用户是否选择了文件
        File file=fileChooser.getSelectedFile();    //获得文件对象
        //获得文件的绝对路径
        ta_showProperty.append("文件的绝对路径是:"+file.getAbsolutePath()+"\n");
        //是否为隐藏文件
        ta_showProperty.append("该文件是隐藏文件吗?"+file.isHidden()+"\n");
        FileReader reader;    //声明字符流
        BufferedReader in;    //声明字符缓冲流
        try
        {
            reader=new FileReader(file);    //创建字符流
            in=new BufferedReader(reader);    //创建字符缓冲流
            String info=in.readLine();    //从文件中读取一行信息
            while(info!=null)
            {
                //判断是否读到内容
                ta_showText.append(info+"\n");    //把读到的信息追加到文本域中
                info=in.readLine();    //继续读下一行信息
            }
            in.close();    //关闭字符缓冲流
            reader.close();    //关闭字符流
        }
        catch(Exception ex)
        {
            ex.printStackTrace();    //输出栈踪迹
        }
    }
}

(4) 运行程序,单击“打开”按钮,选择一个 TXT 文件。图 1 所示为查看文件属性效果,图 2 所示为查看文件内容效果。单击“退出”按钮,可以关闭程序。

查看文件属性

图1 查看文件属性

查看文件内容

图2 查看文件内容

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值