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<String> 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<String> implements ComboBoxModel<String> {
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;
}
}
執行結果為 :
自定義了一個實現 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<String> 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<String> { // 繼承抽象類 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;
}
}
執行結果為 :
還可以使用 DefaultListModel 類建立列表框,該類擴充套件了 AbstractListModel 類,所以也可以通過 DefaultListModel 物件向上轉型為 ListModel 介面初始化列表框,同時 DefaultListModel 類提供了 dModel.addElement() 方法實現將內容新增至列表框中。
eg 1.2-4 使用 DefaultListModel 類建立列表框 。
final String[] flavors = { "列表1", "列表2", "列表3", "列表4", "列表5", "列表6" };
final DefaultListModel<String> dModel = new DefaultListModel<String>();
final JList<String> 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 中比較常用的事件監聽器,很多元件的動作都會使用它監聽,如按鈕被單擊。
事件名稱 | 事件源 | 監聽介面 | 新增或刪除相應型別監聽器的方法 |
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();
}
}
執行結果為 :
在例子中,為按鈕設定了動作監聽器。由於獲取時間監聽時需要獲取實現 ActionListener 介面的物件,所以定義了一個內部類 jbAction 實現 ActionListener 介面,同時在該內部類中實現了 actionPerformed() 方法,也就是在 actionPerformed() 方法中定義當用戶單擊該按鈕後實現怎樣的功能。
3.3 焦點時間監聽器
焦點事件(FocusEvent)監聽器在實際專案開發中應用也比較廣泛,如將游標焦點離開一個文字框時需要彈出一個對話方塊,或者將焦點返回給該文字框等。
事件名稱 | 事件源 | 監聽介面 | 新增或刪除相應型別監聽器的方法 |
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();
}
}
執行結果為 :
在例子中,為文字框元件添加了焦點事件監聽器。這個監聽器需要實現 FocusListener 介面。在該介面中定義了兩個方法,分別為 focusLost() 與 focusGained() 方法,其中 focusLost() 方法是在元件失去焦點時呼叫的,而 focusGained() 方法是在元件獲取焦點呼叫的。本例需要實現在文字框失去焦點時彈出相應對話方塊的功能,所以重寫 focusLost() 方法,同時在為文字框新增監聽時使用了匿名內部類的形式,將實現 FocusListener 介面物件傳遞給 addFocusListener() 方法。