Download presentation
Presentation is loading. Please wait.
1
視窗程式設計 5.文字欄位相關設計 Chih Hung Wang Reference:
1. Java 2 視窗程式設計,文魁出版社,位元文化編著 (2008) (教科書) 2. 深入研究Java Swing (第二版),上奇資訊股份有限公司,黃嘉輝著 (2013) 3. Java SE 6.0視窗程式設計之道,碁峰出版社,黃嘉輝著 (2008) 4. Java 初學指引,博碩文化,陳錦輝著 (2010) 視窗程式設計 5.文字欄位相關設計 Chih Hung Wang
2
Swing的文字元件 Swing提供許多用於處理文字輸入的元件,如:文字欄位、密碼欄、格式化文字欄位、文字區…等。在javax.swing套件內,將提供以下6個用於建立文字元件的類別。 JTextField(文字欄) JPassword(密碼欄) JFormattedTextField(格式化文字欄) JTextArea(文字區) JTextPane(文字面版) JEditorPane(文字編輯面版) 文字欄位與密碼欄 本節將運用範例5-1介紹文字欄位與密碼欄的應用,並說明如何監聽ActionEvent事件與CaretEvent事件。
3
範例 5-1 import javax.swing.*; //引用套件 import javax.swing.event.*;
import java.awt.*; import java.awt.event.*; public class LabelFieldEX extends JFrame{ JLabel lbName = new JLabel("帳號(N) : ", JLabel.RIGHT); JLabel lbPW = new JLabel("密碼(P) : ", JLabel.RIGHT); JTextField tfName = new JTextField(20); JPasswordField pfPW = new JPasswordField(20); JLabel lbEnter = new JLabel("[密碼]欄按下 Enter 取得的資料 : "), lbCaret = new JLabel("[帳號]欄游標的位置 : "); //定義實作CaretListener介面的監聽器類別 class FieldCaretListener implements CaretListener { public void caretUpdate(CaretEvent e){ //回應事件的方法 if( e.getDot() == e.getMark()){ //判斷getDot()方法與getMark()方法的取得值是否相同 lbCaret.setText("[帳號]欄游標的位置 : " + e.getDot()); //取得游標目前的位置 } else lbCaret.setText("[帳號]欄游標的選取範圍 : [" + e.getDot() + "至" + e.getMark() + "]"); //選取範圍的結尾位置
4
FieldCaretListener fcl = new FieldCaretListener();
//宣告監聽CaretEvent事件的監聽器物件 //以匿名內部類別的方式定義並宣告監聽器物件 ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e) { JPasswordField source = (JPasswordField) e.getSource(); //取得事件來源物件 //回應ActionEvent事件時, 更新lbEnter標籤的內容 lbEnter.setText("[密碼]欄按下 Enter 取得的資料 : [" + new String(pfPW.getPassword()) + "]"); } }; LabelFieldEX(){ lbName.setDisplayedMnemonic('N'); //設定使用N搭配Alt鍵做為助憶鍵 lbName.setLabelFor(tfName); //設定lbName標籤為tfName文字欄位的名稱 lbPW.setDisplayedMnemonic('P'); //設定使用P搭配Alt鍵做為記憶鍵 lbPW.setLabelFor(pfPW); //設定lbPW標籤為tfPW文字欄位的名稱 //設定密碼欄使用的遮罩字元
5
tfName.addCaretListener(fcl); //註冊CaretEvent事件的監聽器
pfPW.addActionListener(al); //註冊回應ActionEvent事件的監聽器 JPanel jpCenter = new JPanel(new GridLayout(2, 2, 5, 5)); jpCenter.add(lbName); //將元件加入JPanel子容器 jpCenter.add(tfName); jpCenter.add(lbPW); jpCenter.add(pfPW); JPanel jpLabel = new JPanel(new GridLayout(2, 1, 5, 5)); jpLabel.add(lbCaret); jpLabel.add(lbEnter); Container cp = getContentPane(); //取得內容面版 BorderLayout bl = (BorderLayout)cp.getLayout(); //取得佈局管理員 bl.setVgap(10); //設定垂直間距為10 cp.add(jpCenter); //將元件加入面版 cp.add(jpLabel, BorderLayout.SOUTH); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //設定關閉視窗將預設結束程式 setSize(300, 150); //設定視窗框架大小 setVisible(true); //顯示視窗框架 } public static void main(String args[]) { new LabelFieldEX(); //宣告視窗框架物件
6
ActionEvent事件與CaretEvent事件的回應
文字欄位 JTextField類別用於建立輸入文字資料的欄位,呼叫getText()方法將可取得輸入文字欄位的字串,呼叫setText()方法則可設定欄位內容。若傳入null,將清除欄位內容。 若欲以標籤顯示文字欄位的名稱,可呼叫JLabel元件的setLabelFor()方法,設定標籤顯示某文字欄位的名稱。至於可將游標移至該文字欄位的助憶鍵( 字元),則需呼叫setDisplayedMnemonic()方法設定。 密碼欄 JPasswordField元件用於建立供使用者輸入密碼的文字欄位,使用方式與JTextField類別大致相同。輸入資料後,畫面將顯示遮罩字元,預設的遮罩字元為『*』,欲更改可呼叫setEchoChar()方法。 ActionEvent事件與CaretEvent事件的回應 當於文字欄位與密碼欄內,按下 鍵將觸發ActionEvent事件。若欲回應ActionEvent事件的監聽器類別時,必須實作java.awt.event套件的ActionListener介面(3-2節)。以下敘述將示範以匿名內部類別的方式,定義並宣告監聽ActionEvent事件的監聽器物件。在監聽器裡,將呼叫ActionEvent物件的getSource()方法,取得發出事件的來源物件(第39行),然後取得密碼欄內的輸入值,並顯示於lbEnter標籤。
7
void caretUpdate(CaretEvent e)
若移動欄位內的游標,將觸發CaretEvent事件,而回應CaretEvent事件的監聽器類別,則需實作CaretListener介面。該介面將定義caretUpdate()方法規格如下: void caretUpdate(CaretEvent e) CaretEvent事件類別除繼承EventObject類別定義的方法,還提供下表說明方法。
8
格式化文字欄位 範例 範例5-2將示範如何運用JFormattedTextField類別建立格式化文字欄位,執行結果如下圖所示。
5-3-2 格式化文字欄位的建立與運作 格式化文字欄位的機制 欲建立格式化文字欄位必須使用JFormattedTextField類別。JFormattedTextField類別繼承於JTextField類別,並增加自訂格式的支援。 JFormattedTextField類別處理輸入欄位之資料格式的運作機制,牽涉到兩種物件,分別為格式物件(formatter)與格式物件建立器(formatter factory)。格式物件用於監看輸入至欄位之資料是否符合格式,格式物件建立器則負責產生格式物件。
9
Text屬性與Value屬性 JFormattedTextField類別儲存輸入值的屬性有text與value兩種,text屬性繼承自JTextField類別,將儲存目前輸入於欄位的值。value屬性則由JFormattedTextField類別定義,儲存確定輸入,且符合格式要求的值。 格式化文字欄位的運作 當使用者於欄位內輸入值時,text屬性將儲存輸入值,但並不會立即更新value屬性,直到使用者將焦點移出欄位或按下 鍵,確認輸入值後,格式物件才會依照格式設定,判斷輸入值是否符合要求。 在完成輸入前,按下ESC鍵將取消輸入,欄位值將回復為上次輸入符合格式要求的值,也就是value屬性值。若輸入值符合格式要求,則確認時,將以輸入至欄位的text值更新value屬性值。若不符合要求,則將發生以下兩種情況。 第一種、輸入不符合要求的字元時,即無法輸入,且電腦會發出警告音。 第二種、欄位輸入不符合要求的資料後,當焦點離開欄位後,欄位將取消輸入的資料,欄位的顯示值將恢復為原始值(value屬性)。此時,若按下Enter鍵確定資料完成輸入,電腦將發出警告音。
10
JFormattedTextField類別
12
下表將介紹JFormattedTextField類別的常用方法。
13
5-3-4 格式物件建立器 一般情況下,欲自訂格式物件建立器時,應繼承DefaultFormatterFactory類別,而不需實作AbstractFormatterFactory抽象類別。 DefaultFormatterFactory類別將依照欄位的不同情況,指定欄位使用不同格式物件。下表將說明各種格式物件的使用情況。
14
5-3-5 格式物件 DefaultFormatter 當未指定JFormattedTextField類別使用的格式物件時,預設建構子將指定使用javax.swing.text.DefaultFormatter物件處理各種類型物件的格式化。DefaultFormatter類別的繼承架構如下所示。 下表將介紹幾個重要的方法:
16
MaskFormater MaskFormatter類別繼承自DefaultFormatter類別,繼承架構如下所示。 MaskFormatter類別將允許自訂控制資料格式之遮罩(mask)。所謂的遮罩是指由一組特定符號組成的字串,將規範欄位內特定位置可以出現的合法字元。宣告元件時,將遮罩字串傳入建構子,或呼叫setMask()方法設定。下表為建立遮罩時,可以使用的字元。
17
未出現在上表的字元將顯示於欄位內,且無法更改。以下為幾種常用的遮罩設定示範。
下表將說明MaskFormatter類別的建構子與常用方法。
19
InternationalFormatter
InternationalFormatter類別繼承於DefaultFormatter類別,將用於指定格式處理String與資料值的轉換,繼承架構如下所示。 NumberFormatter NumberFormatter類別繼承於InternationalFormatter類別,繼承架構如下所示。 DateFormatter類別 DateFormatter類別繼承於InternationalFormatter類別,繼承架構如下圖所示。
20
以PropertyChangeListener監聽value屬性
欲監聽元件某屬性值的變化時,可以呼叫java.awt.Container類別的addPropertyChangeListener()方法,註冊欲監聽某屬性的PropertyChangeListener物件。addPropertyChangeListener()方法的規格如下: public void addPropertyChangeListener( String propertyName, PropertyChangeListener listener) 而回應事件的監聽器物件,必須實作PropertyChangeListener介面,此介面規範的propertyChange()方法將執行事件的回應,規格如下。 void propertyChange(PropertyChangeEvent evt) 下表將介紹PropertyChangeEvent的常用方法:
21
資料的驗證 一般來說,資料驗證需求較常運用於輸入文字的元件。當配合5-3節介紹的格式化文字欄位時,則更能夠建立控制資料輸入的完整機制。範例5-3將示範如何定義驗證物件,執行身份證號碼、生日與電話號碼格式的驗證,執行結果如圖所示。 InputVerifier類別 InputVerifier類別為javax.swing套件的抽象類別,下表將說明該類別的建構子與方法。
22
身份證號碼的驗證規則如下: 身份證號碼總共10位 第1位為英文字母 第2位數字可代表性別,男生為 1,女生為 2。 最後一位數字為檢查碼,英文字母與第2至9位數字按照驗證公式運算後,其結果必須符合檢查碼。 驗證公式將把第1位英文字母轉換為整數,各英文字母對應的數值與代表意義,說明如下:
23
驗證公式的計算分成以下兩個部分: 按照上表將英文轉成對應的整數,個位數乘以9,再加上十位數。 將第2位到第9位的數字由左到右依序乘上8、7、6、…、2、1。 將(1)與(2)相加,再用10減去計算結果的個位數字必須等於檢查碼。 下圖以A 為例說明如何運用以上公式執行驗證:
24
文字區與捲動軸 範例 範例5-4將為您介紹如何運用JTextArea類別、JScrollPane類別建立具有捲動軸,可供使用者輸入數行文字的文字區。同時示範CaretEvent事件與DocumentEvent事件的回應。執行結果如圖所示。 5-5-2 建立文字區的JTextArea類別 JTextArea類別的繼承架構如下所示。
25
下表將介紹JTextArea類別常用的建構子:
27
建立捲動軸的JScrollPane類別 JScrollPane類別用於建立捲軸面版,以便為其他Swing元件加上捲軸,以顯示超過文字區可顯示範圍的內容。繼承架構如下所示。 下表將介紹JScrollPane類別的建構子:
29
回應DocumentEvent事件與CaretEvent事件
至於文字區內容變動事件的監聽,則必須運用DocumentEvent事件。但請注意!DocumentEvent事件是由文字區的Document物件丟出,不是JTextArea物件,因此,必須呼叫getDocument()方法取得文字區的Document物件(第32行),再呼叫addDocumentListener()方法,註冊回應事件的DocumentListener物件(第36~44行)。
30
EX 5-4 import javax.swing.*;
import javax.swing.text.*; //引用包含Document介面的套件 import javax.swing.event.*; //引用包含CaretListener介面的套件 import java.awt.*; import java.awt.event.*; //引用處理事件的event套件 public class TextAreaEX extends JFrame{ JTextArea taText = new JTextArea(5, 30); //宣告文字區物件, 並定義為5列30行 JScrollPane spText = new JScrollPane(taText); //以文字區物件建立捲軸面版 JLabel lbText = new JLabel("文字區 :"); JLabel lbTextPos = new JLabel("顯示游標位置"); JLabel lbDocAct = new JLabel("顯示文字區內容的編輯動作"); //定義實作CaretListener介面回應CaretEvent事件的監聽器 CaretListener cl = new CaretListener(){ public void caretUpdate(CaretEvent e){ lbTextPos.setText("文字區游標位置 : " + e.getDot()); if(e.getDot() != e.getMark()) //判斷是否執行範圍選取 lbTextPos.setText(lbTextPos.getText() + " 選取範圍從 " + e.getDot() + "至" + e.getMark()); } }; TextAreaEX(){ taText.setLineWrap(true); //設定文字區自動斷行 taText.setFont(new Font("Times-Roman", Font.BOLD, 15)); //設定使用的字型 taText.addCaretListener(cl); //註冊回應CaretEvent事件的監聽器 Document doc = taText.getDocument(); //取得文字區的Document物件 EX 5-4
31
//註冊Document物件之事件的監聽器, 以回應文字內容的新增與刪除動作,
//並示範在呼叫addDocumentListener()時, 定義監聽器類別 doc.addDocumentListener(new DocumentListener(){ public void insertUpdate(DocumentEvent e) { //資料新增動作 lbDocAct.setText("資料新增至文字區"); } public void removeUpdate(DocumentEvent e) { //資料刪除動作 lbDocAct.setText("移除文字區內容"); public void changedUpdate(DocumentEvent e) { } }); //建立包含顯示文字區狀態之標籤的Box容器 Box bxShow = new Box(BoxLayout.Y_AXIS); bxShow.add(lbTextPos); bxShow.add(lbDocAct); Container cp = getContentPane(); //取得內容面版 cp.setLayout(new FlowLayout(FlowLayout.LEFT)); //設定使用FlowLayout配置 cp.add(lbText); //將元件加入面版 cp.add(spText); cp.add(bxShow); //設定視窗關閉動作、視窗大小, 並顯示視窗 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 230); setVisible(true); public static void main(String args[]) { new TextAreaEX(); //建立視窗框架
Similar presentations