第14章探討了Swing組件集合的JSpinner所提供的動態輸入選擇控制項。在本章中,我們將會瞭解Swing基本文本組件的準系統。更為進階的文本組件將會下一章中進行探討。
Swing組件集合包含五個文本組件。他們共用一個共同的父類,JTextComponent,其中定義了所有的文本組件的更同行為。
JTextComponent的直接子類是JTextField,JTextArea以及JEditorPane。JTextField用於單行的單屬性文本(也就是單一的字型與單一的顏色)。JTextField有一個子類,JPasswordField,用於JTextField用作密碼輸入的情況。JTextArea用於單一屬性文本的多行輸入。JEditorPane是可以支援多屬性輸入編輯的通用編輯器。其子類JTextPane是輸入普通文字格式設定而定製的。在這兩個類中,除了文本,輸入還可以圖片與組件。
15.1 Swing文本組件概述
類似於所有其他的Swing組件,文本組件生活在MVC的世界中。顯示在圖15-1中的組件,類的階層圖,是各種可用的UI委託。UI委託模型的其餘部分是文本視圖,他基於View類,我們會在第16章進行進一步的討論。
注意,所有的JTextComponent子類位於javax.swing包中。除了事件相關的部分,本章中所討論的支援介面與類都位於javax.swing.text包(或是子包)中。Swing特定的,文本相關的事件部分位於javax.swing.event包中,其餘的位於java.awt.event與java.beans中。
每一個組件的模型都是Document介面的實現,他有五個擴充(或是實現)。單屬性群組件使用PlainDocument類作為其資料模型,而多屬性群組件使用DefaultStyledDocument作為其模型。所有這些類派生自AbstractDocument類,在其中定義了他們共同的Document介面實現。DefaultStyleDocument類也實現了StyledDocument介面,他是Document用於支援多屬性內容的擴充。另一個Document實現,HTMLDocument,用於JEditorPane的內容類型為text/html的情況。為了限制到這些文檔的輸入,我們可以使用DocumentFilter類。
本章中以及第16章中將要討論的許多其他具有共同的文本組件特性。類似於許多其他的Swing組件,我們可以自訂群組件的觀感而無需建立新的UI委託。對於文本組件,Highlighter,Caret以及NavigationFilter介面分別描述了文本如何高亮顯示,在哪裡插入文本以及如何限制滑鼠位置,從而使得我們可以自訂文本組件的外觀以及輸入行為。另外,InputMap/ActionMap類定義了擊鍵與文本動作之間的綁定,從而允許我們非常容易的修改文本組件的行為。
其他的組件模型部分被設計用於事件處理。我們並沒有被限制使用KeyListener/KeyEvent或是TextEvent/TextListener綁定來處理輸入驗證。Swing組件同時使用DocumentEvent/DocumentListener組合(以及第2章所描述的InputVerifier)。這種組合提供了一種更為靈活的輸入驗證方式,特別是在Swing文本組件的MVC環境中。額外的事件處理是通過在第2章所介紹的AbstractAction功能擴充來實現的。這就是用於將鍵盤綁定與Action實現相關聯的TextAction類,我們將會在第16章中進行詳細的討論。文字框架中的許多部分是通過所謂的EditorKit串連在一起的,我們也會在第16章中進行討論。
注意,由於Swing文本組件類之間的相互串連,我們將會在本章中與第16章中的大量引用關聯。我們可以自由的在兩章之間進行跳轉並且接下來閱讀某一功能的詳細討論。
15.2 JTextComponent類
JTextComponent類是用作所有文本視圖的組件的父類。他描述了所有文本組件所共用的共同行為。在這些共同行為中包括用於選中支援的Highlight,用於在內容中瀏覽的Caret,通過action屬性(Action實現數組)支援的命令集合,通過KeyMap或是InputMap/ActionMap組合支援的鍵盤綁定集合,一個Scrollable介面實現,從而每一個特定的文本組件都可以放在JScrollPane中,以及儲存在組件中的文本。如果所有的這些聽起來需要大量的管理,不要擔心。本章將會為我們給出指導。
15.2.1 JTextComponent屬性
表15-1顯示了JTextComponent的27個屬性。這些屬性覆蓋我們所期望的文本組件功能。
這些屬性被分為八個基本類別:
- 資料模型:document屬性用於所有文本組件的資料模型。text屬性用於將這個資料模型看作一個String。
- 顏色:caretColor,disabledTextColor, selectedTextColor與selectionColor屬性,以及繼承的foreground與background屬性指定了渲染游標,禁止文本,所選文本,所選文本的背景,常規文本以及常規文本的背景等顏色。
- Caret:caret,caretPosition與navigationFilter屬性用於在文檔中瀏覽。
- Highlighter:highlighter,selectionStart與selectionEnd屬性負責高亮顯示文檔中的selectedText部分。
- Margin:margin屬性用於指定常值內容距離文本組件的邊界多遠顯示。
- 事件:actions與keymap屬性描述了文本組件支援哪些功能。對於actions屬性的Action[]情況,功能是我們為了事件處理可以關聯到組件的一系列ActionListener實現。例如,不必建立一個ActionListener來執行剪下、複製與粘貼操作,我們會發現actions屬性中的相應的Action並將其關聯到組件。keymap的作用類似,但是他是將Action關聯到特定的鍵。例如,他包含一個按鍵映射條目用於處理當PageUp鍵被按下時如何響應。caretListsener屬性允許我們發現觀察文本組件的CaretListener對象集合。dragEnabled設定描述了組件是否支援在組件中拖放文本。(要瞭解Swing中的拖放支援資訊,可以查看第19章。)
- 滾動介面:屬性preferredScrollableViewportSize, scrollableTracksViewportHeight,與scrollableTracksViewportWidth是相應的Scrollable介面方法的實現。
- 狀態:editable與focusTraversable屬性描述了文本組件的各種狀態。editable允許我們文本組件設定為唯讀。對於唯讀focusTraversable屬性,當他們被使能時文本組件位於資訊迴圈中(也就是我們可以使用Tab鍵遍曆)。focusAccelerator用於相鄰的JLabel在其labelFor屬性設定文本組件的情況,允許我們使用JLabel的可視化熱鍵將焦點移動到文本組件。componentOrientation設定描述了組件的文本如何繪製。將這一特性於類似Hebrew那樣由右到左的語言並不是必須,但卻是繪製字元的最好方法。JTextComponent由JComponent繼承了opaque屬性。當opaque屬性被設定為false時,文本組件後面的地區內容會被看穿,如果需要,可以允許我們具有一個圖片背景。圖15-2顯示了這一效果。
列表15-1是用於產生圖15-2的源碼。如果我們取消setOpaque(false)一行,則背景不會顯現。
package swingstudy.ch13; import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.Graphics;import java.awt.Image; import javax.swing.GrayFilter;import javax.swing.ImageIcon;import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTextArea; public class BackgroundSample { /** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub Runnable runner = new Runnable() {public void run() {JFrame frame = new JFrame("Background Example");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final ImageIcon imageIcon = new ImageIcon("draft.gif");JTextArea textArea = new JTextArea() {Image image = imageIcon.getImage();Image grayImage = GrayFilter.createDisabledImage(image);{setOpaque(false);// instance initializer}public void paint(Graphics g) {g.drawImage(grayImage, 0, 0, this);super.paint(g);}};JScrollPane scrollPane = new JScrollPane(textArea);frame.add(scrollPane, BorderLayout.CENTER);frame.setSize(255, 2550);frame.setVisible(true);}};EventQueue.invokeLater(runner);} }15.2.2 JTextComponent操作JTextComponent為文本控制項上所執行的許多操作定義了基本的架構。
- I/O:public void read(Reader in, Object description)與public void write(Writer out)方法(都拋出IOException)允許我們簡單的讀取或是寫入文本組件內容。
- 剪下板訪問:public void cut(), public void copy()與public void paste()方法提供了到系統剪下板的直接存取。
- 位置:public void moveCaretPosition(int position)方法允許我們定位caret。位置表示標明由文本組件開始處到caret之前的字元數的一維定位。
- 選中:public void replaceSelection(String content), public void selectAll()與public void select(int selectionStart, int selectionEnd)方法允許我們組件中的內容部分與替換所選擇的內容。
- Conversion:public Rectange modelToView(int position) throws BadLocationException與public int viewToModel(Point point)方法允許我們(或者更可能的是系統)將JTextComponent內的一個位置映射到特定文本UI委託的內容表示中的映射。
現在我們已經概述了JTextComponent類,現在是瞭解其不同的子類的時候了。首先是JTextField,他將會被用來示範剛才所列出的操作。