Java: Cách sử dụng Text Component


Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên

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ệ thống cấp bậc của Swing của các thành phần văn bản

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.

Một ứng dụng cung cấp một mẫu của mỗi thành phần văn bản Swing

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.

A snapshot of TextComponentDemo, which contains a customized text pane and a standard text area

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 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ới JTextPane (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ượng Action của riêng bạn. DefaultEditorKit định nghĩa một số hữu ích các lớp con của Action.

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:

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.

Lưu ý: Theo mặc định thì mỗi chỉnh sửa có thể quay ngược lại sẽ quay ngược một ký tự đầu vào. Có thể với một số nỗ lực để nhóm các chỉnh sửa để cho một loạt các key stroke được kết hợp thành một chỉnh sửa có thể quay ngược lại. Việc nhóm các chỉnh sửa theo cách này sẽ yêu cầu bạn định nghĩa một lớp để chặn các sự kiện chỉnh sửa có thể quay ngược từ tài liệu, kết hợp chúng nếu thích hợp và chuyển tiếp các kết quả tới bộ lắng nghe chỉnh sửa có thể quay ngược lại.

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 AbstractActionUndoAction 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:

The hierarchy of document classes that javax.swing.text provides.

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 setNavigationFilterphươ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 setCaretphươ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ả
Thiết lập các thuộc tính
Những phương thức này được định nghĩa trong lớp JTextComponent.
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
Thao tác với các lựa chọn
Những phương thức này được định nghĩa trong lớp JTextComponent.
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ả
Chuyển đổi các vị trí giữa Model và View
Những phương thức này được định nghĩa trong lớp JTextComponent.
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ả
Các câu lệnh chỉnh sửa văn bản
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
(inDefaultEditorKit)
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
(inDefaultEditorKit)
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
(inStyledEditorKit)
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ả
Các lớp và interface đại diện cho tài liệu
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ả
Làm việc với tài liệu
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)
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ả
Thao tác với các Highlighter dấu nháy và lựa chọn
Những phương thức này được định nghĩa trong lớp JTextComponent.
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ả
Đọc và viết văn bản
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

» Tiếp: JFormattedTextField
« Trước: JProgressBar
Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên
Copied !!!