Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)

一、列表组件

    Swing 中提供了两种列表组件,分别为下拉列表框与列表框。下拉列表框与列表框都是带有一系列项目的组件,用户可以从中选择需要的项目。列表框较下拉列表框更直观,它将所有的项目罗列在列表框中;但下拉列表框较列表框更为便捷、美观,它将所有的项目隐藏起来,当用户选用其中的项目时才会显现出来。

    1.1 下拉列表框组件

    1.1.1  JComboBox 类

    下拉列表框是一个带条状的显示区,它具有下拉功能,在下拉列表框的右方存在一个倒三角形的按钮,当用户单击该按钮时,下拉 列表框中的项目将会以列表形式显示出来。

    Swing 中的下拉列表框使用 JComboBox 类对象来表示,它是 javax.swing.JComponent 类的子类。它的常用构造方法如下 : 

    ( 1 ) :public JComboBox() 。

    ( 2 ) :public JComboBox(ComboBoxModel dataModel) 。

    ( 3 ) :public JComboBox(Objet[] arrayDate) 。

    ( 4 ) :public JComboBox(Vector vector) 。

    在初始化下拉列表框时,可以选择同时指定下拉列表框中的项目内容,也可以在程序中使用其他方法设置下拉列表框中的内容,下拉列表框中的内容可以被封装在 ComboBoxModel 类型、数组或 Vector 类型中。

    1.1.2  JComboBox 模型

    在开发过程中,一般将下拉列表框中的项目封装为 ComboBoxModel 的情况比较多。 ComboBoxModel 为接口,它代表一般模型,可以自定义一个类实现该接口,然后再初始化 JComboBox 对象时向上转型为 ComboBoxModel 接口类型,但是必须实现以下两种方法 :

    ( 1 ) :public void setSelectedIten(Object item) 。

    ( 2 ) :public Object getSelectedItem() 。

    其中,setSelectedItem() 方法用于设置下拉列表框中的选中项, getSelectedItem() 方法用于返回下拉列表框中的选中项,有了这两个方法,就可以轻松地对下拉列表框中的项目进行操作。

    自定义这个类除了实现该接口之外,还可以继承 AbstractListModel 类,在该类中也有两个操作下拉列表框的重要方法 :

    ( 1 ) : getSize()  :返回列表的长度 。

    ( 2 ) : getElementAt(int index)  :返回指定索引处的值 。

    eg 1.1.2 在项目中创建 JComboBoxModelTest 类,使该类继承 JFrame 类称为窗体组件,在类中创建下拉列表框,并添加到窗体中。

package com.SwingDemo;

import java.awt.*;
import javax.swing.*;

public class JComboBoxModelTest extends JFrame {
    private static final long serialVersionUID = 1L;
    JComboBox jBox = new JComboBox<>(new MyComboBox());
    JLabel jLabel = new JLabel("请选择证件:");
    public JComboBoxModelTest() {
        setSize(new Dimension(160, 180));
        setVisible(true);
        setTitle("在窗口中设置下拉列表框");
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        Container container = getContentPane();
        container.setLayout(new FlowLayout());
        container.add(jBox);
        container.add(jLabel);
    }

    public static void main(String[] args) {
        new JComboBoxModelTest();
    }
}

class MyComboBox extends AbstractListModel implements ComboBoxModel {
    private static final long serialVersionUID = 1L;
    String selectedItem = null;
    String[] teStrings = { "身份证", "军人证", "学生证", "工作证" };
    @Override
    public String getElementAt(int index) {        //根据索引返回值
        return teStrings[index];
    }
    @Override
    public int getSize() {        //返回下拉列表框项目的数目
        return teStrings.length;
    }
    @Override
    public void setSelectedItem(Object anItem) {        //设置下拉列表框项目
        selectedItem = (String) selectedItem;
    }
    @Override
    public Object getSelectedItem() {        //获取下拉列表框项目
        return selectedItem;
    }
    public int getIndex() { 
        for (int i = 0; i < teStrings.length; i++) {
            if (teStrings[i].equals(getSelectedItem())) {
                return i;
            }
        }
        return 0;
    }
}
    运行结果为 :

Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第1张图片        Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第2张图片

    自定义了一个实现 ComboBoxModel 接口并继承 AbstractListModel 类的类,这样这个类就可以实现或重写该接口与该类中的重要方法,同时在定义下拉列表框时,只要将该类向上转型为 ComboBoxModel 接口即可。

    1.2 列表框组件

    列表框(JList)与下拉列表框的区别不仅表现在外观上,当激活下拉列表框时,还会出现下拉列表框中的内容;但列表框只是在窗体上占据固定的大小,如果需要列表框具有滚动效果,可以将列表框放入滚动面板中。用户在选择列表框中的某一项时,按住 Shift 键并选择列表框中的其他项目,则当前选项和其他项目之间的选项将全部被选中;也可以按住 Ctrl 键并单击列表框中的单个项目,这样可以是列表框中被单击的项目反复切换非选择状态或选择状态。

    Swing 中使用 JList 类对象来表示列表框,常用的构造方法 :

    ( 1 ) :public void JList() 。

    ( 2 ) :public void JList(Object[] listData) 。

    ( 3 ) :public void JList(Vector listData) 。

    ( 4 ) :public void JList(ListModel dataModel) 。

    在上述构造方法中,存在一个没有参数的构造方法,可以通过在初始化列表框后使用 setListData() 方法对列表框进行设置,也可以在初始化的过程中对列表框中的项目进行设置。设置的方式有3 中类型,包括数组、Vector 类型和 ListModel 类型。

    当使用数组作为构造方法的参数时,首先需要创建列表项目的数字,然后再利用构造方法来初始化列表框。

    eg 1.2-1 使用数组作为初始化列表框的参数 。

String[] contents = {"列表 1","列表 2","列表 3","列表 4"};
JList jlist = new JList(contents);
   eg 1.2-2 如果使用上述构造方法中的第 3 个构造方法,将 Vector 类型的数据作为初始化 JList 组件的参数。
Vector vector = new Vector();
JList jlist = new JList(vector);
vector.add("列表 1");
vector.add("列表 2");
vector.add("列表 3");
vector.add("列表 4");

    如果使用 ListModel 模型为参数,需要创建 ListModel 对象。ListModel 是 Swing 包中的一个接口,它提供了获取列表框属性的方法。但是在通常情况下,为了使用户不完全实现 ListModel 接口中的方法,通常自定义一个类继承实现该接口的抽象类 AbstractListModel 。在这个类中提供了 getElementAt() 与 getSize() 方法,其中 getElementAt() 方法代表根据项目的索引获取列表框中的值,而 getSize() 方法用于获取列表框中的项目个数。

    eg 1.2-3 在项目中创建 JListTest 类,是该类继承 JFrame 类成为窗体组件,在该类中创建列表框,并添加到窗体中。

package com.SwingDemo;

import java.awt.*;
import javax.swing.*;

public class JListTest extends JFrame {
    private static final long serialVersionUID = 1L;
    public JListTest() {
        Container container = getContentPane();
        container.setLayout(null);
        JList jList = new JList<>(new MyListModel());
        JScrollPane jScrollPane = new JScrollPane(jList);
        jScrollPane.setBounds(10, 10, 100, 100);
        container.add(jList);
        setTitle("在这个窗体使用了列表框");
        setVisible(true);
        setSize(200, 150);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    }

    public static void main(String[] args) {
        new JListTest();
    }
}

class MyListModel extends AbstractListModel {        // 继承抽象类 AbstractListModel
    private static final long serialVersionUID = 1L;
    // 设置列表框内容
    private String[] contents = { "列表 1", "列表 2", "列表 3", "列表 4", "列表 5", "列表 6" };
    @Override
    public String getElementAt(int index) {        // 重写 getElementAt() 方法
        if (index < contents.length) {
            return contents[index++];
        } else {
            return null;
        }
    }
    @Override
    public int getSize() {        // 重写 getSize() 方法
        return contents.length;
    }
}

    运行结果为 :

Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第3张图片        Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第4张图片

    还可以使用 DefaultListModel 类创建列表框,该类扩展了 AbstractListModel 类,所以也可以通过 DefaultListModel  对象向上转型为 ListModel 接口初始化列表框,同时 DefaultListModel  类提供了 dModel.addElement() 方法实现将内容添加至列表框中。

    eg 1.2-4 使用 DefaultListModel 类创建列表框 。

final String[] flavors = { "列表1", "列表2", "列表3", "列表4", "列表5", "列表6" };
final DefaultListModel dModel = new DefaultListModel();
final JList jList = new JList<>(dModel);        //实例化 JList 对象
for(int i=0;i<4;i++) {
    dModel.addElement(flavors[i]);        //为模型添加内容
}

二、文本组件

    文本组件在实际项目开发中使用最为广泛,尤其是文本框与密码框组件,通过文本组件可以很轻松地处理单行文字、多行文字、口令字段 。

    2.1 文本框组件

    文本框(JTextField)用来显示或编辑一个单行文本,在 Swing 中通过 javax.swing.JTextField 类对象创建,该类继承了 javax.swing.text.JTextComponent 类。

    文本框常用的构造方法 :

    ( 1 )  :public JTextField() 。

    ( 2 )  :public JTextField(String text) 。

    ( 3 )  :public JTextField(int fieldwidth) 。 

    ( 4 )  :public JTextField(String text , int fieldwidth) 。

    ( 5 )  :public JTextField(Document docModel , String text , int fieldWidth) 。

    可以通过在初始化文本框时设置文本框的默认文字、文本框的长度等实现。

    eg 2.1 在项目中创建 JTextFieldTest 类,使该类继承 JFrame 类成为窗体组件,在该类中创建文本框和按钮组件,并添加到窗体中。    

package com.SwingDemo;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class JTextFieldTest extends JFrame {
    private static final long serialVersionUID = 1L;
    public JTextFieldTest() {
        setSize(250, 100);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        Container container = getContentPane();
        getContentPane().setLayout(new FlowLayout());
        final JTextField jTextField = new JTextField("aaa", 20);
        final JButton jButton = new JButton("清除");
        container.add(jTextField);
        container.add(jButton);
        jTextField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                jTextField.setText("触发事件");
            }
        });
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                jTextField.setText("");
                jTextField.requestFocus();
            }
        });
        setVisible(true);
    }
    public static void main(String[] args) {
        new JTextFieldTest();
    }
}

    运行结果为 :

                在例子中主要设置了一个文本框和一个按钮,然后分别为文本框和按钮设置事件,当用户将光标焦点落于文本框中并按下 Enter 键时,文本框将执行 actionPerformed() 方法中设置的操作。同时还为按钮添加了相应的时间,当用户单击“清除”按钮时,文本框中的字符串将被清除 。

    2.2 密码框组件

    密码框(JPasswordField)与文本框的定义与用法基本相同,唯一不同的是密码框将用户输入的字符串以某种符号进行加密。密码框对象是通过 javax.swing.JPasswordField 类来创建的,JPasswordField 类的构造方法与 JTextField 类的构造方法非常相似。

    ( 1 )  :public JPasswordField() 。

    ( 2 )  :public JPasswordField(String text) 。

    ( 3 )  :public JPasswordField(int fieldwidth) 。 

    ( 4 )  :public JPasswordField(String text , int fieldwidth) 。

    ( 5 )  :public JPasswordField(Document docModel , String text , int fieldWidth) 。

    eg 2.2  定义密码框 。

JPasswordField jp = new JPasswordField();
jp.setEchoChar('#');//设置回显字符

     在 JPasswordField 类中提供一个 setEchoChar() 方法,可以改变密码框的回显字符 。

    2.3 文本域组件

    Swing 中任何一个文本区域都是 JTextArea 类型的对象。JTextArea 常用的构造方法如下 :

    ( 1 )  :public JTextArea () 。

    ( 2 )  :public JTextArea (String text) 。

    ( 3 )  :public JTextArea (int rows , int columns) 。 

    ( 4 )  :public JTextArea (Document doc) 。

    ( 5 )  :public JTextArea (Document doc, String text , int rows , int columns) 。

    可以在初始化文本域时提供默认文本以及文本域的长与宽 。

    eg 2.3  在项目中创建 JTextAreaTest 类,使该类继承 JFrame 类成为窗体组件,在该类中创建 JTextArea 组件的实例,并添加到窗体中 。

package com.SwingDemo;

import java.awt.*;
import javax.swing.*;

public class JTextAreaTest extends JFrame {
    private static final long serialVersionUID = 1L;

    public JTextAreaTest() {
        setSize(200, 100);
        setTitle("定义自动换行的文本域");
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        Container container = getContentPane();
        JTextArea jArea = new JTextArea("文本域", 6, 6);
        jArea.setLineWrap(true);        // 可以自动换行
        container.add(jArea);
        setVisible(true);
    }

    public static void main(String[] args) {
        new JTextAreaTest();
    }
}

    运行结果为 :

    

    JTextArea 类中存在一个 setLineWrap()  方法,该方法用于设置文本域是否可以自动换行,如果将该方法的参数设置为 true ,文本域将自动换行,否则则不自动换行 。

三 、常用事件监听器    

    之前所讲的组件本身并不带有任何功能。例如,在窗体中定义一个按钮,当用户单击该按钮时,虽然按钮可以凹凸显示,但在窗体中并没有实现任何功能。这是需要为按钮添加特定事件监听器,该监听器负责处理用户单击按钮后实现的功能。

    3.1 监听事件简介

    在 Swing 事件模型中由 3 个分离的对象完成对事件的处理,分别为事件源、事件以及监听程序。事件源触发一个事件,它被一个或多个“监听器”接收,监听器负责处理事件。

    所谓事件监听器,实质上就是一个“实现特定类型监听器接口”的类对象。具体地说,事件几乎都以对象来表示,它是某种事件类的对象,事件源(如按钮)会在用户作出相应的动作(如按钮被按下)时产生事件对象,如动作事件对应 ActionEvent 类对象,同时要编写一个监听器的类必须实现相应的接口,如 ActionEvent  类对应的是 ActionListener 接口,需要获取某个事件对象就必须实现相应的接口,同时需要将接口中的方法一一实现。最后事件源(按钮)调用相应的方法加载这个“实现特定类型监听器接口”的类对象,所有的事件源都具有 addXXXListener() 和 removeXXXListener() 方法(其中 XXX 方法表示监听事件类型),这样就可以为组件添加或移除相应的事件监听器 。

    3.2 动作事件监听器 

    动作事件(ActionEvent)监听器是 Swing 中比较常用的事件监听器,很多组件的动作都会使用它监听,如按钮被单击。

表 3.2 动作事件监听器
事件名称 事件源 监听接口 添加或删除相应类型监听器的方法
ActionEvent JButton 、 JList 、 JTextField 等 ActionListenter addActionListener() 、removeActionListener()

    eg 3.2 在项目中创建 SimpleEvent 类,使该类继承 JFrame 类成为窗体组件,在类中创建按钮组件,为按钮组件添加动作监听器,然后将按钮组件添加到窗体中。

package com.SwingDemo;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class SimpleEvent extends JFrame {
    private static final long serialVersionUID = 1L;
    private JButton jb = new JButton("我是按钮,单击我");
    public SimpleEvent() {
        setLayout(null);
        setSize(200, 100);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        Container container = getContentPane();
        container.add(jb);
        jb.setBounds(10, 10, 100, 30);
        jb.addActionListener(new jbAction());
        setVisible(true);
    }

    class jbAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            jb.setText("我被单击了");
        }
    }

    public static void main(String[] args) {
        new SimpleEvent();
    }
}

    运行结果为 : 

Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第5张图片        Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第6张图片

    在例子中,为按钮设置了动作监听器。由于获取时间监听时需要获取实现 ActionListener 接口的对象,所以定义了一个内部类 jbAction 实现 ActionListener 接口,同时在该内部类中实现了 actionPerformed() 方法,也就是在 actionPerformed() 方法中定义当用户单击该按钮后实现怎样的功能。

    3.3 焦点时间监听器

    焦点事件(FocusEvent)监听器在实际项目开发中应用也比较广泛,如将光标焦点离开一个文本框时需要弹出一个对话框,或者将焦点返回给该文本框等。

表 3.3 焦点事件监听器
事件名称 事件源 监听接口 添加或删除相应类型监听器的方法
FocusEvetn Component 以及派生类 FocusListener addFocusListener() 、removeFocusListener()

    eg 3.3 在项目中创建 FocusEventTest 类,使该类继承 JFrame 类成为窗体组件,在类中创建文本框组件,并为文本框添加焦点事件监听器,将文本框组件添加到窗体中。

package com.SwingDemo;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class FocusEventTest extends JFrame {
    private static final long serialVersionUID = 1L;

    public FocusEventTest() {
        setSize(250, 100);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        Container container = getContentPane();
        container.setLayout(new FlowLayout());
        final JLabel jLabel = new JLabel();
        container.add(jLabel);
        JTextField jTextField1 = new JTextField("请单击其他文本框", 10);
        JTextField jTextField2 = new JTextField("请单击我", 10);
        container.add(jTextField1);
        container.add(jTextField2);
        jTextField1.addFocusListener(new FocusListener() {
            // 组件失去焦点时调用的方法
            @Override
            public void focusLost(FocusEvent e) {
                JOptionPane.showMessageDialog(null, "文本框失去焦点");
            }

            // 组件获取键盘焦点时调用的方法
            @Override
            public void focusGained(FocusEvent e) {

            }
        });
        setVisible(true);
    }

    public static void main(String[] args) {
        new FocusEventTest();
    }
}

    运行结果为 :

Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第7张图片    Java核心(Swing 程序设计4-列表组件、文本组件、常用时间监听器)_第8张图片

    在例子中,为文本框组件添加了焦点事件监听器。这个监听器需要实现 FocusListener 接口。在该接口中定义了两个方法,分别为 focusLost() 与 focusGained() 方法,其中 focusLost() 方法是在组件失去焦点时调用的,而  focusGained() 方法是在组件获取焦点调用的。本例需要实现在文本框失去焦点时弹出相应对话框的功能,所以重写 focusLost() 方法,同时在为文本框添加监听时使用了匿名内部类的形式,将实现 FocusListener 接口对象传递给 addFocusListener() 方法。 



你可能感兴趣的:(Java)