Java: Cách sử dụng Text Component
Swing cung cấp tới sáu loại text component, đồng thời hỗ trợ các lớp và interface để cho phép cung cấp những loại text phức tạp nhất. Tất cả các Swing text component đều thừa kế từ lớp cha JTextComponent
.
Hình dưới đây thể hiện sơ đồ phân cấp của JTextComponent
.
Hình dưới đây thể hiện một ứng dụng có tên TextSamplerDemo
, trong đó nó trình bày tất cả các loại text component.
Ví dụ TextSamplerDemo
sử dụng các thành phần văn ban theo cách thức cơ bản. Bảng dưới đây sẽ cho ta biết thêm về những gì bạn có thể làm với từng loại thành phần văn bản.
Nhóm | Mô tả | Lớp Swing |
---|---|---|
Text Controls | Còn được gọi đơn giản là text field, dùng để hiển thị chỉ một dòng văn bản có thể chỉnh sửa. Cũng giống như nút lênh, chúng tạo ra các sự kiện hành động. Sử dụng chúng để thu thập một lượng nhỏ các thông tin dạng văn bản từ người dùng và thực hiện một hành động sau khi hoàn tất việc nhập văn bản. | JTextField và các lớp con của nó là JPasswordField và JFormattedTextField |
Plain Text Areas | JTextArea có thể hiển thị nhiều dòng văn bản có thể chỉnh sửa. Mặc dù text area có thể hiển thị văn bản với bất kỳ font chữ nào, nhưng tất cả các văn bản trong text area đều phải có cùng một loại font chữ. Text area được sử dụng với mục đích cho phép người dùng nhập văn bản không định dạng với kích thước bất kỳ, hoặc để hiển thị thông tin trợ giúp không định dạng. |
JTextArea |
Styled Text Areas | Một thành phần văn bản có định kiểu có thể hiển thị văn bản có thể chỉnh sửa và cho phép sử dụng nhiều hơn một loại font chữ. Một số thành phần văn bản định kiểu còn cho phép nhúng hình ảnh và thậm chí còn cho phép nhúng cả các những thành phần khác. Các thành phần văn bản định kiểu là các thành phần mạnh mẽ và đa dạng phù hợp cho các nhu cầu cao cấp, và cung cấp nhiều cách để tùy biến hơn so với các thành phần văn bản khác.
Do chúng rất mạnh mẽ và linh hoạt, nên các thành phần văn bản định kiểu thường đòi hỏi nhiều công sức lập trình ban đầu hơn để thiết lập và sử dụng. Một khả năng nữa mà thành phần văn bản định kiểu có được đó là biên tập viên có thể dễ dàng nạp với các định dạng văn bản từ một URL, giúp chúng hữu ích cho việc hiển thị thông tin trợ giúp không thể chỉnh sửa. |
JEditorPane và lớp con của nóJTextPane |
Khả năng của Text Component
Lớp JTextComponent
là nền tảng cho các thành phần văn bản Swing. Lớp này cung cấp các khả năng tùy chỉnh sau cho tất cả các lớp con của nó:
- Một mô hình, được biết đến như một tài liệu, để quản lý nội dung của thành phần.
- Một view, để hiển thị thành phần trên màn hình.
- Một bộ điều khiển, được biết đến như là một bộ biên tập (editor kit), dùng để đọc và viết văn bản và thực hiện khả năng chỉnh sửa với các hành động.
- Hỗ trợ undo và redo vô hạn.
- Một dấu nháy cắm và hỗ trợ cho người nghe thay đổi dấu nháy và bộ lọc điều hướng.
Dưới đây là hình ảnh của ví dụ có tên TextComponentDemo
, ví dụ này có chứa đựng những khả năng ở trên. Mặc dù ví dụ TextComponentDemo
có chứa một trường tùy biến là JTextPane
, nhưng những khả năng đã nói ở trên đều được thừa hưởng từ lớp con JTextComponent
.
Thành phần văn bản phía trên là cửa sổ văn bản tùy chỉnh, thành phần văn bản phía dưới là một thể hiện của JTextArea
, nó phục vụ như là một nhật ký để thông tất cả các thay đổi về những nội dung của cửa sổ văn bản. Dòng trạng thái ở dưới cùng của cửa sổ báo cáo hoặc vị trí của việc lựa chọn hoặc là vị trí của con nháy soạn thảo tùy thuộc vào việc văn bản được chọn thế nào.
Dùng ví dụ TextComponentDemo
để tham chiếu, ta sẽ tìm hiểu những vấn đề sau:
- Liên kết các hành động văn bản với Menus và nút
- Liết kết các hành động văn bản với các Key Stroke
- Thực hiện Undo và Redo
- Các khái niệm: About Documents
- Thực hiện một bộ lọc tài liệu
- Lắng nghe sự thay đổi của tài liệu
- Lắng nghe sự thay đổi của dấu nháy soạn thảo và lựa chọn
- Các khái niệm: Về bộ soạn thảo
- Liên kết nhanh chữ Bằng Menus và Buttons
- Liên kết nhanh chữ Bằng Strokes chính
Liên kết các hành động văn bản với Menu và nút
Tất cả các thành phần văn bản Swing đều hỗ trợ các lệnh chỉnh sửa tiêu chuẩn như cắt, sao chép, dán, và chèn các ký tự. Mỗi lệnh chỉnh sửa được đại diện và thực hiện bởi một đối tượng Action
. Action cho phép bạn kết hợp một lệnh với một thành phần giao diện, chẳng hạn như là một mục menu hoặc nút, và do đó xây dựng một giao diện xung quanh một thành phần văn bản.
Bạn có thể gọi phương thức getActions
trên bất kỳ thành phần văn bản nào để nhận được một mảng chứa tất cả các hành động được hỗ trợ bởi thành phần này. Nó cũng có thể tải mảng các hành động vào một HashMap
nên chương trình của bạn có thể truy xuất một hành động theo tên. Dưới đây là mã từ ví dụ TextComponentDemo
gồm những hành động từ cửa sổ văn bản và tải chúng vào HashMap
.
private HashMap<Object, Action> createActionTable(JTextComponent textComponent) {
HashMap<Object, Action> actions = new HashMap<Object, Action>();
Action[] actionsArray = textComponent.getActions();
for (int i = 0; i < actionsArray.length; i++) {
Action a = actionsArray[i];
actions.put(a.getValue(Action.NAME), a);
}
return actions;
}
Phương thức dưới đây dùng để truy xuất một hành động theo tên của nó từ bản đồ băm:
private Action getActionByName(String name) {
return actions.get(name);
}
Bạn có thể sử dụng cả hai phương thức đúng như trong chương trình của bạn.
Các mã sau đây cho thấy cách mà mục trình đơn cắt được tạo ra và gắn với hành động loại bỏ các văn bản từ các thành phần văn bản.
protected JMenu createEditMenu() {
JMenu menu = new JMenu("Edit");
...
menu.add(getActionByName(DefaultEditorKit.cutAction));
...
Đoạn mã trên lấy các hành động theo tên bằng cách sử dụng phương thức hữu ích đã thể hiện ở trên đây. Sau đó nó sẽ thêm hành động vào menu. Đó là tất cả những gì bạn cần làm. Menu và hành động sẽ quan tâm đến mọi thứ. Lưu ý rằng tên của hành động được lấy từ DefaultEditorKit
. Bộ tài liệu này cung cấp hành động để chỉnh sửa văn bản cơ bản và là lớp cha của tất cả các bộ biên tập được cung cấp bởi Swing. Vì vậy, khả năng của nó là có sẵn cho tất cả các thành phần văn bản trừ khi chúng được ghi đè bởi một tuỳ biến.
Để hiệu quả, các thành phần văn bản sẽ chia sẻ hành động. Đối tượng Action
được trả về bởi getActionByName( DefaultEditorKit.cutAction)
được chia sẻ bởi JTextArea
không thể chỉnh sửa ở dưới cùng của cửa sổ. Đặc tính chia sẻ này có hai nhánh quan trọng:
- Nói chung, bạn không nên thay đổi các đối tượng
Action
mà bạn nhận được từ bộ công cụ biên tập. Nếu bạn làm thế, những thay đổi sẽ ảnh hưởng đến tất cả các thành phần văn bản trong chương trình của bạn. - Các đối tượng Action có thể hoạt động trên các thành phần văn bản khác trong chương trình, đôi khi nhiều hơn bạn dự định. Trong ví dụ này, mặc dù không thể chỉnh sửa, nhưng
JTextArea
chia sẻ các hành động vớiJTextPane
(chọn một số văn bản trong vùng văn bản, sau đó chọn mục trình đơn cut-to-clipboard. Bạn sẽ nghe thấy một tiếng bíp vì vùng văn bản là không thể chỉnh sửa). Nếu bạn không muốn chia sẻ thì bạn cần tạo thể hiển của đối tượngAction
của riêng bạn.DefaultEditorKit
định nghĩa một số hữu ích các lớp con củaAction
.
Dưới đây là đoạn mã tạo menu Style và đặt các mục trình đơn Bold trong nó:
protected JMenu createStyleMenu() {
JMenu menu = new JMenu("Style");
Action action = new StyledEditorKit.BoldAction();
action.putValue(Action.NAME, "Bold");
menu.add(action);
...
StyledEditorKit
cung cấp các lớp con của Action
để thực hiện các lệnh chỉnh sửa cho văn bản theo kiểu. Bạn sẽ thấy rằng thay vì nhận được các hành động từ các bộ biên tập, mã lệnh này tạo ra một thể hiện của lớp BoldAction
. Như vậy, hành động này không được chia sẻ với bất kỳ thành phần văn bản khác, và việc thay đổi tên của nó sẽ không ảnh hưởng đến bất kỳ thành phần văn bản nào.
Liên kết các hành động văn bản với các Key Stroke
Ngoài việc liên kết hành động với thành phần giao diện, bạn cũng có thể kết hợp một hành động với một key stroke bằng cách sử dụng bản đồ đầu vào của một thành phần văn bản.
Cửa sổ văn bản trong ví dụ TextComponentDemo
hỗ trợ bốn tổ hợp phím không được cung cấp theo mặc định sau đây:
- Ctrl-B để di chuyển dấu nháy soạn thảo trở về trước một ký tự
- Ctrl-F để di chuyển dấu nháy soạn thảo về phía sau một ký tự
- Ctrl-N để di chuyển dấu nháy soạn thảo xuống một dòng
- Ctrl-P để di chuyển dấu nháy soạn thảo lên một dòng
Đoạn mã sau thêm tổ hợp phím Ctrl-B liên kết với các cửa sổ văn bản:
InputMap inputMap = textPane.getInputMap();
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_B, Event.CTRL_MASK);
inputMap.put(key, DefaultEditorKit.backwardAction);
Đầu tiên, đoạn mã có được bản đồ đầu vào của thành phần văn bản. Tiếp theo, nó tìm một đối tượng KeyStroke
đại diện cho tổ hợp phím phím Ctrl-B. Cuối cùng, mã lệnh liên kết với key stroke tới Action
để di chuyển con trỏ về phía sau.
Thực hiện Undo và Redo
Việc thực hiện undo và redo gồm hai phần:
- Nhớ lại việc chỉnh sửa có thể quay ngược lại.
- Thực hiện lệnh Undo và Redo và cung cấp một giao diện người dùng cho chúng.
Phần 1: Nhớ lại việc chỉnh sửa có thể quay ngược lại
Để hỗ trợ Undo và Redo, một thành phần văn bản cần phải nhớ từng chỉnh sửa xảy ra, thứ tự các chỉnh sửa, và những cần thiết để hoàn tác (undo) từng chỉnh sửa. Chương trình ví dụ sử dụng một thể hiện của lớp UndoManager
để quản lý danh sách các chỉnh sửa có thể quay ngược lại. Trình quản lý undo được tạo ra trong đó các biến thành viên được khai báo như sau:
protected UndoManager undo = new UndoManager();
Bây giờ, chúng ta hãy nhìn vào cách chương trình phát hiện những chỉnh sửa có thể quay ngược lại và thêm chúng vào trong trình quản lý undo.
Một tài liệu thông báo cho bộ lắng nghe quan tâm đến bất cứ khi nào một chỉnh sửa có thể quay ngược lại xảy ra trên các nội dung tài liệu. Một bước quan trọng trong việc thực hiện undo và redo là đăng ký một bộ lắng nghe chỉnh sửa có thể quay ngược lại trên tài liệu của thành phần văn bản. Mã lệnh sau thêm một thể hiện của MyUndoableEditListener
tới tài liệu của khung văn bản:
doc.addUndoableEditListener(new MyUndoableEditListener());
Bộ lắng nghe chỉnh sửa có thể quay ngược lại được sử dụng trong ví dụ của ta để thêm chỉnh sửa tới danh sách của trình quản lý undo:
protected class MyUndoableEditListener
implements UndoableEditListener {
public void undoableEditHappened(UndoableEditEvent e) {
//Remember the edit and update the menus
undo.addEdit(e.getEdit());
undoAction.updateUndoState();
redoAction.updateRedoState();
}
}
Lưu ý rằng phương thức này sẽ cập nhật hai đối tượng: undoAction
và redoAction
. Đây là những đối tượng hành động gắn liền với các mục menu Undo và Redo tương ứng. Bước tiếp theo sẽ cho bạn thấy cách tạo ra các mục trình đơn và cách để thực hiện hai hành động này.
Phần 2: Thực hiện các lệnh Undo và Redo
Bước đầu tiên trong việc thực hiện các lệnh undo và redo là tạo các hành động để đưa vào menu Edit.
JMenu menu = new JMenu("Edit");
//Undo and redo là các hành động do chính ta tạo ra
undoAction = new UndoAction();
menu.add(undoAction);
redoAction = new RedoAction();
menu.add(redoAction);
...
Undo và Redo được thực hiện bằng cách tùy chỉnh các lớp con của AbstractAction
: UndoAction
và RedoAction
. Những lớp này là lớp bên trong của lớp chính của ví dụ.
Khi người sử dụng gọi lệnh undo
thì phương thức actionPerformed
của lớp UndoAction
được gọi như sau:
public void actionPerformed(ActionEvent e) {
try {
undo.undo();
} catch (CannotUndoException ex) {
System.out.println("Unable to undo: " + ex);
ex.printStackTrace();
}
updateUndoState();
redoAction.updateRedoState();
}
Phương thức này sẽ gọi phương thức undo của trình quản lý và cập nhật các mục trình đơn để phản ánh tình trạng undo/redo mới.
Tương tự như vậy, khi người dùng gọi lệnh redo
, thì phương thức actionPerformed
của lớp RedoAction
sẽ được gọi:
public void actionPerformed(ActionEvent e) {
try {
undo.redo();
} catch (CannotRedoException ex) {
System.out.println("Unable to redo: " + ex);
ex.printStackTrace();
}
updateRedoState();
undoAction.updateUndoState();
}
Phương thức này cũng tương tự như undo, chỉ khác là nó gọi phương thức redo của trình quản lý.
Hầu hết các mã lệnh trong các lớp UndoAction
và RedoAction
được dành để cho phép và vô hiệu hóa các hành động phù hợp với trình trạng hiện thời, và thay đổi tên của các mục trình đơn để phản ánh các chỉnh sửa được undo hoặc redo thành công.
Chú ý: Việc thực hiện Undo và Redo trong ví dụ
TextComponentDemo
được lấy từ bản demo NotePad
đi kèm với phần mềm JDK. Nhiều lập trình viên cũng sẽ có thể sao chép việc undo/redo này mà không sửa đổi.
Các khái niệm: Về tài liệu
Cũng giống như các thành phần Swing khác, một thành phần văn bản sẽ tách dữ liệu của nó (được gọi là model) từ view về các dữ liệu của nó.
Model của thành phần văn bản được biết đến như một tài liệu và là một thể hiện của một lớp mà thực thi giao diện Document
. Một tài liệu sẽ cung cấp các dịch vụ sau đây cho một thành phần văn bản:
- Chứa văn bản. Một tài liệu sẽ lưu trữ nội dung văn bản trong đối tượng
Element
, nó có thể đại diện cho bất kỳ cấu trúc văn bản logic nào, chẳng hạn như đoạn văn, hoặc văn bản chia sẽ các style. - Cung cấp sự hỗ trợ cho việc chỉnh sửa văn bản thông qua các phương thức
remove
vàinsertString
. - Thông báo cho bộ lắng nghe tài liệu và bộ lắng nghe chỉnh sửa có thể quay ngược lại các thay đổi của văn bản.
- Quản lý đối tượng
Position
, đối tượng này theo dõi và đánh dấu một địa điểm cụ thể trong văn bản ngay cả khi văn bản được sửa đổi. - Cho phép bạn để có được thông tin về các văn bản, chẳng hạn như chiều dài của nó, và các phân đoạn của văn bản như là một chuỗi.
Các gói phần mềm văn bản Swing chứa một giao diện con của Document
là StyledDocument
, nó bổ sung sự hỗ trợ cho việc đánh dấu lên các văn bản với các style. Một lớp con của JTextComponent
là JTextPane
, nó yêu cầu rằng tài liệu của nó phải là một StyledDocument
chứ không phải chỉ đơn thuần là một Document
.
Gói javax.swing.text
cung cấp hệ thống phân cấp sau đây của các lớp tài liệu, trong đó thực hiện các văn bản chuyên ngành cho nhiều lớp con JTextComponent
:
PlainDocument
là tài liệu mặc định cho các text field, password field, và text area. PlainDocument
cung cấp một container cơ bản cho văn bản trong đó tất cả các văn bản được hiển thị với cùng một phông chữ. Mặc dù mỗi cửa sổ trình soạn thảo là một thành phần định kiểu, nhưng nó sử dụng một thể hiện của PlainDocument
một cách mặc định. Tài liệu mặc định cho một JTextPane
tiêu chuẩn là một thể hiện của DefaultStyledDocument
- một container cho văn bản định kiểu theo một định dạng không xác định. Tuy nhiên, thể hiện tài liệu được sử dụng bởi bất kỳ cửa sổ soạn thảo văn bản hoặc cửa sổ văn bản nào đều phụ thuộc vào loại nội dung ràng buộc với nó. Nếu bạn sử dụng phương thức setPage
để tải văn bản vào một cửa sổ trình soạn thảo hoặc cửa sổ văn bản, thì thể hiện tài liệu được sử dụng bởi các cửa sổ có thể thay đổi.
Mặc dù bạn có thể thiết lập tài liệu của một thành phần văn bản nào đó, nó thường dễ dàng hơn để cho phép nó thiết lập một cách tự động, và nếu cần thiết, ta sử dụng một bộ lọc tài liệu để thay đổi cách dữ liệu của thành phần văn bản được thiết lập. Bạn có thể thực hiện các tùy chỉnh nhất định, hoặc bằng cách cài đặt một bộ lọc tài liệu hoặc bằng cách thay thế tài liệu của thành phần văn bản theo ý của bạn. Ví dụ, khung văn bản trong ví dụ TextComponentDemo
có một bộ lọc tài liệu có giới hạn số lượng ký tự mà nó có thể chứa.
Thực hiện một bộ lọc tài liệu
Để thực hiện một bộ lọc tài liệu, ta tạo ra một lớp con của DocumentFilter
và sau đó gắn nó vào một tài liệu bằng cách sử dụng phương thức setDocumentFilter
được định nghĩa trong lớp AbstractDocument
. Mặc dù nó có thể có các tài liệu mà không phân cấp từ AbstractDocument
, nhưng mặc định thì các thành phần văn bản Swing sử dụng lớp con AbstractDocument
cho tài liệu của chúng.
Ứng dụng TextComponentDemo
có một bộ lọc tài liệu là DocumentSizeFilter
, nó giới hạn số ký tự mà khung văn bản có thể chứa. Dưới đây là đoạn code tạo bộ lọc và gắn nó vào tài liệu của khung văn bản:
...//Where member variables are declared:
JTextPane textPane;
AbstractDocument doc;
static final int MAX_CHARACTERS = 300;
...
textPane = new JTextPane();
...
StyledDocument styledDoc = textPane.getStyledDocument();
if (styledDoc instanceof AbstractDocument) {
doc = (AbstractDocument)styledDoc;
doc.setDocumentFilter(new DocumentSizeFilter(MAX_CHARACTERS));
}
Để giới hạn các ký tự được phép trong tài liệu, thì DocumentSizeFilter
ghi đè phương thức insertString
của lớp DocumentFilter
, phương thức này được gọi mỗi lần văn bản được chèn vào tài liệu. Nó cũng sẽ ghi đè phương thức replace
, mà rất có thể sẽ được gọi khi người dùng dán (paste) vào văn bản mới. Nói chung, việc chèn văn bản có thể xảy ra khi người dùng soạn hoặc dán văn bản mới, hoặc khi phương thức setText
được gọi. Dưới đây là sự thực hiện của phương thức insertString
của lớp DocumentSizeFilter
:
public void insertString(FilterBypass fb, int offs,
String str, AttributeSet a)
throws BadLocationException {
if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)
super.insertString(fb, offs, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
Đoạn mã cho phương thức replace
là tương tự. Tham số FilterBypass
cho các phương thức được định nghĩa bởi lớp DocumentFilter
chỉ đơn giản là một đối tượng cho phép tài liệu được cập nhật một cách an toàn.
Do bộ lọc tài liệu trên là có liên quan với các bổ sung cho dữ liệu của tài liệu, nên nó chỉ ghi đè các phương thức insertString
và replace
. Hầu hết các bộ lọc tài liệu sẽ ghi đè được phương thức remove
của lớp DocumentFilter
.
Lắng nghe những thay đổi trên tài liệu
Bạn có thể đăng ký hai loại bộ lắng nghe khác nhau trên một tài liệu: bộ lắng nghe tài liệu và bộ lắng nghe chỉnh sửa có thể undo. Phần này ta sẽ tìm hiểu về bộ lắng nghe tài liệu. Để biết thông tin về bộ lắng nghe chỉnh sửa có thể undo bạn xem phần Thực hiện Undo và Redo.
Một tài liệu sẽ thông báo cho bộ lắng nghe tài liệu đã đăng ký những thay đổi trong tài liệu. Sử dụng một bộ lắng nghe tài liệu để tạo một phản ứng khi văn bản được chèn vào hoặc lấy ra từ một tài liệu, hoặc khi thay đổi style văn bản.
Ví dụ TextComponentDemo
sử dụng một bộ lắng nghe tài liệu để cập nhật các bản ghi thay đổi bất cứ khi nào một thay đổi được thực hiện ở cửa sổ văn bản. Các dòng mã sau đây đăng ký một thể hiện của lớp MyDocumentListener
như một bộ lắng nghe trên tài liệu của khung văn bản:
doc.addDocumentListener(new MyDocumentListener());
Dưới đây là sự thực hiện của lớp MyDocumentListener
:
protected class MyDocumentListener implements DocumentListener {
public void insertUpdate(DocumentEvent e) {
displayEditInfo(e);
}
public void removeUpdate(DocumentEvent e) {
displayEditInfo(e);
}
public void changedUpdate(DocumentEvent e) {
displayEditInfo(e);
}
private void displayEditInfo(DocumentEvent e) {
Document document = (Document)e.getDocument();
int changeLength = e.getLength();
changeLog.append(e.getType().toString() + ": "
+ changeLength + " character"
+ ((changeLength == 1) ? ". " : "s. ")
+ " Text length = " + document.getLength()
+ "." + newline);
}
}
Bộ lắng nghe thực hiện ba phương thức để xử lý ba loại sự kiện tài liệu khác nhau: chèn, xóa bỏ, và thay đổi style. Các thể hiện của StyledDocument
có thể kích hoạt cả ba loại sự kiện này. Các thể hiện của PlainDocument
chỉ kích hoạt những sự kiện chèn và loại bỏ.
Hãy nhớ rằng bộ lọc tài liệu cho khung văn bản này giới hạn số lượng ký tự cho phép trong tài liệu. Nếu bạn cố gắng thêm nhiều văn bản hơn sự cho phép của bộ lọc tài liệu thì nó sẽ khóa sự thay đổi và phương thức insertUpdate
của bộ lắng nghe sẽ không được gọi. Bộ lắng nghe tài liệu được thông báo về những thay đổi chỉ khi thay đổi đã xảy ra.
Bạn có thể muốn thay đổi văn bản của tài liệu trong một bộ lắng nghe tài liệu. Tuy nhiên, bạn không bao giờ nên sửa đổi các nội dung của một thành phần văn bản từ bên trong một bộ lắng nghe tài liệu. Nếu bạn làm thế, chương trình sẽ có khả năng bị bế tắc. Thay vào đó, bạn có thể sử dụng một formatted text field hoặc cung cấp một bộ lọc tài liệu.
Lắng nghe những thay đổi của dấu nháy và sự lựa chọn
Ví dụ TextComponentDemo
sử dụng một bộ lắng nghe dấu nháy để hiển thị vị trí hiện tại của dấu nháy, hoặc nếu văn bản được chọn thì xác định phạm vi của vùng chọn.
Lớp lắng nghe dấu nháy trong ví dụ này là một lớp con của JLabel
. Dưới đây là mã lệnh nhãn cho bộ lắng nghe dấu nháy và tạo cho nó một bộ lắng nghe dấu nháy của cửa sổ văn bản:
//Create the status area
CaretListenerLabel caretListenerLabel = new CaretListenerLabel("Caret Status");
...
textPane.addCaretListener( caretListenerLabel);
Mỗi bộ lắng nghe dấu nháy phải thực hiện một phương thức là caretUpdate
, nó được gọi mỗi lần di chuyển dấu nháy hoặc thay đổi lựa chọn. Dưới đây là sự thực thi phương thức caretUpdate
của CaretListenerLabel
:
public void caretUpdate(CaretEvent e) {
//Get the location in the text
int dot = e.getDot();
int mark = e.getMark();
if (dot == mark) { // no selection
try {
Rectangle caretCoords = textPane.modelToView(dot);
//Convert it to view coordinates
setText("caret: text position: " + dot +
", view location = [" +
caretCoords.x + ", " + caretCoords.y + "]" +
newline);
} catch (BadLocationException ble) {
setText("caret: text position: " + dot + newline);
}
} else if (dot < mark) {
setText("selection from: " + dot + " to " + mark + newline);
} else {
setText("selection from: " + mark + " to " + dot + newline);
}
}
Như bạn có thể thấy, bộ lắng nghe này sẽ cập nhật nhãn văn bản của nó để phản ánh tình trạng hiện tại của dấu nháy hoặc lựa chọn. Bộ lắng nghe lấy các thông tin để hiển thị từ đối tượng sự kiện dấu nháy.
Tương tự như với các bộ lắng nghe tài liệu, bộ lắng nghe dấu nháy là thụ động. Nó phản ứng với những thay đổi trong các dấu nháy hoặc trong việc lựa chọn, nhưng không làm thay đổi dấu nháy hoặc lựa chọn riêng của mình. Nếu bạn muốn thay đổi các dấu nháy hoặc lựa chọn thì bạn sử dụng một bộ lọc chuyển hướng hoặc một dấu nháy tùy chỉnh.
Thực hiện một bộ lọc điều hướng là tương tự để thực hiện một bộ lọc tài liệu. Đầu tiên, hãy viết một lớp con của NavigationFilter
. Sau đó đính kèm một thể hiện của lớp con cho một thành phần văn bản với các setNavigationFilter
phương pháp.
Bạn có thể tạo dấu nháy tùy chỉnh để tùy chỉnh sự xuất hiện của một dấu nháy. Để tạo ra dấu nháy tùy chỉnh, bạn viết một lớp thực thi giao diện Caret
- có lẽ bằng cách mở rộng lớp DefaultCaret
. Sau đó cung cấp một thể hiện của lớp học của bạn như một đối số cho setCaret
phương thức trên một thành phần văn bản.
Bộ biên soạn
Text component sử dụng một EditorKit
để gắn kết các phần khác nhau của thành phần văn bản với nhau. Bộ biên tập cung cấp view, tài liệu, dấu nháy, và các hành động. Một bộ biên tập có thể đọc và viết các tài liệu với một định dạng cụ thể. Mặc dù tất cả các thành phần văn bản đều sử dụng bộ dụng cụ biên tập, nhưng một số thành phần lại ẩn chúng. Bạn không thể thiết lập hoặc lấy các bộ biên tập được sử dụng bởi một text field hay mộ text area. Khung bộ soạn thảo và khung văn bản cung cấp phương thức getEditorKit
để lấy bộ biên tập hiện tại và phương thức setEditorKit
để thay đổi nó.
Đối với tất cả các thành phần, lớp JTextComponent
cung cấp API để bạn có thể gián tiếp gọi hoặc tùy chỉnh một số khả năng của bộ biên tập. Ví dụ, JTextComponent
cung cấp các phương thức read
và write
, trong đó gọi các phương thức read
và write của
bộ biên tập. JTextComponent
cũng cung cấp một phương thức nữa là getActions để
trả về tất cả các hành động được hỗ trợ bởi một thành phần.
Các gói phần mềm văn bản Swing cung cấp các bộ công cụ biên tập sau đây:
DefaultEditorKit
Đọc và viết văn bản thông thường, và cung cấp một tập cơ bản các lệnh chỉnh sửa. Thông tin chi tiết về cách hệ thống văn bản đối xử với các dòng mới có thể được tìm thấy trong tài liệu API DefaultEditorKit
. Tóm lại, ký tự '\ n' được sử dụng nội bộ, nhưng các tài liệu hay nền tảng tách dòng được sử dụng khi ghi tập tin. Tất cả các bộ công cụ soạn thảo khác đều là con của lớp DefaultEditorKit
.
StyledEditorKit
Đọc và viết văn bản định kiểu, và cung cấp một tập tối thiểu các hành động cho văn bản định kiểu. Lớp này là một lớp con của DefaultEditorKit
và là bộ biên tập được sử dụng bởi JTextPane một cách
mặc định.
HTMLEditorKit
Đọc, viết, và chỉnh sửa HTML. Đây là một lớp con của StyledEditorKit
.
Mỗi bộ công cụ biên tập được liệt kê ở trên đã được đăng ký với lớp JEditorPane
và liên kết với các định dạng văn bản gồm các bộ đọc, viết, và chỉnh sửa. Khi một tập tin được nạp vào một cửa sổ soạn thảo, thì cửa sổ sẽ kiểm tra định dạng của tập tin ngược với bộ dụng cụ đã đăng ký. Nếu một bộ đã đăng ký được tìm thấy có hỗ trợ định dạng file đó, thì cửa sổ sử dụng bộ đó để đọc các tập tin, hiển thị và chỉnh sửa nó. Do đó, cửa sổ biên tập chuyển đối hiệu quả bản thân nó thành một trình biên tập định dạng văn bản. Bạn có thể mở rộng JEditorPane
để hỗ trợ định dạng văn bản của riêng bạn bằng cách tạo ra một bộ biên tập cho nó, và sau đó sử dụng sregisterEditorKitForContentType của
JEditorPane
để kết hợp bộ của bạn với các định dạng văn bản của bạn.
API của Text Component
Phương thức | Mô tả |
---|---|
void setEditable(boolean) boolean isEditable() |
Thiết lập hoặc chỉ định việc người dùng có thể chỉnh sửa văn bản trong thành phần văn bản. |
void setDragEnabled(boolean) boolean getDragEnabled() |
Thiết lập hoặc lấy thuộc tính dragEnabled , giá trị thuộc tính này phải là true để có thể xử lý kéo được trên thành phần này. Giá trị mặc định là false. |
void setDisabledTextColor(Color) Color getDisabledTextColor() |
Thiết lập hoặc lấy màu sắc được sử dụng để hiển thị văn bản khi thành phần văn bản bị vô hiệu. |
void setMargin(Insets) Insets getMargin() |
Thiết lập hoặc lấy giá trị margin giữa văn bản và đường viền của thành phần văn bản. |
Method | Description |
---|---|
String getSelectedText() | Lấy văn bản đang được chọn. |
void selectAll() void select(int, int) |
Chọn tất cả các văn bản hoặc văn bản trong một khoảng được chỉ ra. |
void setSelectionStart(int) void setSelectionEnd(int) int getSelectionStart() int getSelectionEnd() |
Thiết lập hoặc lấy mức độ của sự lựa chọn hiện thời theo chỉ số. |
void setSelectedTextColor(Color) Color getSelectedTextColor() |
Thiết lập hoặc lấy màu của văn bản đã chọn. |
void setSelectionColor(Color) Color getSelectionColor() |
Thiết lập hoặc lấy màu nền của văn bản đã chọn. |
Phương thức | Mô tả |
---|---|
int viewToModel(Point) | Chuyển vị trí được chỉ định trong hệ tọa độ view sang vị trí trong văn bản. |
Rectangle modelToView(int) | Chuyển vị trí được chỉ định trong văn bản sang dạng chữ nhật trong hệ tọa độ view. |
Lớp hoặc phương thức | Mô tả |
---|---|
void cut() void copy() void paste() void replaceSelection(String) (in JTextComponent ) |
Cắt, sao chép, và dán văn bản bằng cách sử dụng clipboard của hệ thống, hoặc thay thế các văn bản được lựa chọn bằng chuỗi được xác định bởi một đối số tương ứng. |
EditorKit | Cung cấp một view, tài liệu, dấu nháy, và hành động của thành phần văn bản, cũng như việc đọc và ghi các tài liệu theo một định dạng cụ thể. |
DefaultEditorKit | Một lớp con cụ thể của EditorKit để cung cấp khả năng soạn thảo văn bản cơ bản. |
StyledEditorKit | Lớp con của Default EditorKit , nó cung cấp khả năng chỉnh sửa bổ sung văn bản định kiểu. |
String xxxxAction (in DefaultEditorKit ) |
Các tên của các hành động được hỗ trợ bởi bộ biên tập mặc định. Xem phần Liên kết các hành động văn bản với Menu và nút. |
BeepAction CopyAction CutAction DefaultKeyTypedAction InsertBreakAction InsertContentAction InsertTabAction PasteAction (in DefaultEditorKit ) |
Các lớp nội dùng để thực hiện các câu lệnh chỉnh sửa văn bản khác nhau. |
AlignmentAction BoldAction FontFamilyAction FontSizeAction ForegroundAction ItalicAction StyledTextAction UnderlineAction (in StyledEditorKit ) |
Các lớp trong dùng đề thực hiện các câu lệnh chỉnh sửa khác nhau cho văn bản định kiểu. |
Action[] getActions() (in JTextComponent ) |
Lấy các hành động được hỗ trợ bởi thành phần hiện thời. Phương thức này sẽ lấy mảng các hành động từ bộ biên tập nếu nó được sử dụng bởi thành phần. |
InputMap getInputMap() (in JComponent ) |
Lấy bản đồ nhập liệu mà liên kết các key stroke tới các hành động. Xem phần Liên kết các hành động văn bản với các key stroke. |
void put(KeyStroke, Object) (in InputMap ) |
Liên kết key được chỉ định tới hành động được chỉ định. Nói chung bạn có thể chỉ định hành động theo tên của nó cho các hành động chỉnh sửa chuẩn được đại diện bởi một hằng chuỗi, chẳng hạn DefaultEditorKit.backwardAction . |
Lớp hoặc Interface | Mô tả |
---|---|
Document | Một giao diện định nghĩa các API trong đó phải được thực hiện bởi tất cả các tài liệu. |
AbstractDocument | Lớp cha trừu tượng thực thi giao diện Document . Đây là lớp cha cho tất cả các tài liệu được cung cấp bởi gói văn bản Swing. |
PlainDocument | Lớp này thực thi giao diện Document . Đây là tài liệu mặc định cho các thành phần văn bản (text field, password field, và text area). Ngoài ra, lớp này còn được sử dụng bởi các khung bộ biên tập và khung văn bản khi tải văn bản thông thường hoặc văn bản không rõ định dạng. |
StyledDocument | Giao diện con của Document . Nó định nghĩa API trong đó phải được thực hiện bởi những tài liệu có hỗ trợ văn bản định kiểu. JTextPane yêu cầu tài liệu của nó phải có kiểu này. |
DefaultStyledDocument | Lớp thực thi giao diện StyledDocument . Đây là tài liệu mặc định cho JTextPane . |
Lớp hoặc phương thức | Mô tả |
---|---|
DocumentFilter | Lớp cha của tất cả các bộ lọc tài liệu. Ta có thể sử dụng bộ lọc tài liệu để thay đổi những gì được thêm vào hoặc xóa từ tài liệu mà không cần phải thực hiện tài liệu.Xem phần Bộ lọc tài liệu. |
void setDocumentFilter(DocumentFilter) (trong AbstractDocument ) |
Thiết lập bộ lọc tài liệu. |
void setDocument(Document) Document getDocument() (trong JTextComponent ) |
Thiết lập hoặc lấy tài liệu cho một thành phần văn bản. |
Document createDefaultModel() (trong JTextField ) |
Tạo một model PlainDocument mặc định. Ghi đè phương thức này để tạo một tài liệu tùy chỉnh thay vì PlainDocument mặc định. |
void addDocumentListener(DocumentListener) void removeDocumentListener(DocumentListener) (trong Document ) |
Thêm hoặc xóa bộ lắng nghe tài liệu. Xem phần Lắng nghe những thay đổi trên tài liệu. |
void addUndoableEditListener(UndoableEditListener) void removeUndoableEditListener(UndoableEditlistener) (trong Document ) |
Thêm hoặc xóa một bộ lắng nghe chỉnh sửa có thể undo. Các bộ lắng nghe chỉnh sửa có thể undo được sử dụng để thực hiện các thao tác Undo và Redo. |
int getLength() Position getStartPosition() Position getEndPosition() String getText(int, int) (trong Document ) |
Các phương thức Document trả về thông tin mô tả khác nhau về tài liệu. |
Object getProperty(Object) void putProperty(Object, Object) (in Document )void setDocumentProperties(Dictionary) Dictionary getDocumentProperties() (trong AbstractDocument ) |
A Document duy trì một tập các thuộc tính mà bạn có thể thao tác với chúng. |
Interface, lớp, hoặc phương thức | Mô tả |
---|---|
Caret | Interface để định nghĩa API cho các đối tượng đại diện cho một điểm chèn trong tài liệu. |
DefaultCaret | Dấu nháy mặc định được sử dụng bởi tất cả các thành phần văn bản. |
void setCaret(Caret) Caret getCaret() |
Thiết lập hoặc lấy đối tượng dấu nháy được sử dụng bởi thành phần văn bản. |
void setCaretColor(Color) Color getCaretColor() |
Thiết lập hoặc lấy màu của dấu nháy. |
void setCaretPosition(int) void moveCaretPosition(int) int getCaretPosition() |
Thiết lập hoặc lấy vị trí hiện thời của dấu nháy trong tài liệu. |
void addCaretListener(CaretListener) void removeCaretListener(CaretListener) |
Thêm hoặc xóa một bộ lắng nghe từ thành phần văn bản. |
NavigationFilter | Lớp cha cho tất cả các bộ lọc điều hướng. Bộ lọc điều hướng cho phép bạn chỉnh sửa các thay đổi dấu nháy về những gì xảy ra trong thành phần văn bản. |
void setNavigationFilter(NavigationFilter) | Đính kèm bộ lọc chuyển hướng tới thành phần văn bản. |
Highlighter | Interface dùng để định nghĩa API cho các đối tượng được sử dụng để làm nổi bật lựa chọn hiện thời. |
DefaultHighlighter | Highlighter mặc định được sử dụng bởi tất cả các thành phần văn bản. |
void setHighlighter(Highlighter) Highlighter getHighlighter() |
Thiết lập hoặc lấy highlighter được sử dụng bởi thành phần văn bản. |
Phương thức | Mô tả |
---|---|
void read(Reader, Object) void write(Writer) (trong JTextComponent ) |
Đọc và viết văn bản. |
void read(Reader, Document, int) void read(InputStream, Document, int) (trong EditorKit ) |
Đọc văn bản từ luồng vào tài liệu. |
void write(Writer, Document, int, int) void write(OutputStream, Document, int, int) (trong EditorKit ) |
Ghi văn bản từ tài liệu ra luồng. |
Nguồn: https://docs.oracle.com/javase/tutorial/uiswing/components/text.html