Java: Cách sử dụng Tree

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Với lớp JTree ta có thể tạo và hiển thị dữ liệu theo dạng phân cấp. Đối tượng JTree thực sự không chứa dữ liệu, nó đơn giản lả chỉ cung cấp cách nhìn dữ liệu.

A tree

Tạo Tree

Ảnh dưới là kết quả của một ứng dụng, trong đó phần trên thể hiện một tree trong thanh cuộn.

TreeDemo

Đoạn mã sau trích từ ví dụ TreeDemo, nó cho ta biết cách tạo một đối tượng JTree và đặt nó vào thanh cuộn:

//Khai báo biến thể hiện:
private JTree tree;
...
public TreeDemo() {
    ...
    DefaultMutableTreeNode top =
        new DefaultMutableTreeNode("The Java Series");
    createNodes(top);
    tree = new JTree(top);
    ...
    JScrollPane treeView = new JScrollPane(tree);
    ...
}

Đoạn mã trên tạo một thể hiện có tên top của lớp DefaultMutableTreeNode và thể hiện này đóng vai trò là gốc của cây, gốc này có tên là "The Java Series". Cấu lệnh tiếp sau sẽ tiến hành tạo cây với gốc là top là đối số của hàm tạo của lớp JTree. Cuối cùng ta đưa cây vào scroll pane.

Còn đây là đoạn mã dùng để tạo các nút (cành) cho cây:

private void createNodes(DefaultMutableTreeNode top) {
    DefaultMutableTreeNode category = null;
    DefaultMutableTreeNode book = null;

    category = new DefaultMutableTreeNode("Books for Java Programmers"); //Tạo cành
    top.add(category);

    //Tutorial gốc
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Tutorial: A Short Course on the Basics",
        "tutorial.html"));
    category.add(book);

    //Tutorial Continued
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Tutorial Continued: The Rest of the JDK",
        "tutorialcont.html"));
    category.add(book);

    //Swing Tutorial
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Swing Tutorial: A Guide to Constructing GUIs",
        "swingtutorial.html"));
    category.add(book);

    //...thêm sách

    category = new DefaultMutableTreeNode("Books for Java Implementers");
    top.add(category);

    //VM
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Virtual Machine Specification",
         "vm.html"));
    category.add(book);

    //Language Spec
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Language Specification",
         "jls.html"));
    category.add(book);
}

Đối số của hàm tạo DefaultMutableTreeNode là đối tượng người dùng, đây là một đối tượng chứa hoặc trỏ tới dữ liệu liên quan đến nút của cây. Đối tượng người dùng có thể là một chuỗi hoặc cũng có thể là một đối tượng tùy chỉnh. Nếu bạn thực thi một đối tượng tùy chỉnh thì bạn nên thực thi phương thức toString của nó và nó sẽ trả về chuỗi được hiển thị cho nút đó. Theo mặc định thì JTree sẽ render mỗi nút bằng cách sử dụng giá trị trả về từ phương thức toString, vậy nên toString cần trả về giá trị có nghĩa. Đôi khi cũng không khả thi khi ghi đè phương thức toString; trong kịch bản như vậy bạn có thể ghi đè phương thức convertValueToText của JTree để ánh xạ đối tượng từ model trong một chuỗi để hiển thị.

Ví dụ như lớp BookInfo ở đoạn mã trên là một lớp tùy chỉnh gồm hai phần dữ liệu là tên sách và URL của tập tin HTML mô tả cuốn sách đó. Phương thức toString được thực thi để trả về tên của cuốn sách. Vì thế mà mỗi nút kết hợp với một đối tượng BookInfo sẽ hiển thị ra tên của sách.


Lưu ý: Ta có thể xác định định dạng văn bản trong nút cây bằng cách đặt thẻ HTML trong chuỗi cho mỗi nút.

Tóm lại: Bạn có thể tạo một cây bằng cách gọi hàm tạo JTree, xác định lớp thực thi TreeNode như là một đối số. Ta cũng nên đặt cây vào scroll pane để đảm bảo nó không chiếm quá nhiều không gian. Ta không cần phải làm bất kỳ điều gì để tạo các nút với chức năng mở rộng hay thu gọn vì hai chức năng này đã được tự động hỗ trợ. Tuy nhiên ta cần phải viết một vài câu lệnh để đảm bảo khi người dùng click chọn một nút nào đó thì sẽ nút đó sẽ phản hồi cho việc click đó. Phần sau đây sẽ mô tả cách lập trình cho hiệu ứng này.

Tạo phản hồi cho nút được chọn

Việc lập trình để tạo phải hồi này khá đơn giản. Cụ thể là ta chỉ cần thực thi bộ lắng nghe (listener) của cây được chọn và đăng ký nó tới cây đó. Đoạn mã sau minh họa cho điều này:

//Khởi tạo cây:
    tree.getSelectionModel().setSelectionMode
            (TreeSelectionModel.SINGLE_TREE_SELECTION);

    //Lắng nghe sự thay đổi.
    tree.addTreeSelectionListener(this);
...
public void valueChanged(TreeSelectionEvent e) {
//Trả về phần tử cuối của lựa chọn
//Phương thức này chỉ hữu dụng khi model được chọn cho phép 1 lựa chọn thôi.
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                       tree.getLastSelectedPathComponent();

    if (node == null)
    //Không nút nào được chọn
    return;

    Object nodeInfo = node.getUserObject();
    if (node.isLeaf()) {
        BookInfo book = (BookInfo)nodeInfo;
        displayURL(book.bookURL);
    } else {
        displayURL(helpURL);
    }
}

Đoạn mã trên thực hiện các công việc sau:

  • Lấy TreeSelectionModel mặc định cho cây sau đó thiết lập mức cao nhất cho nó mỗi khi nó được chọn
  • Đăng ký bộ xử lý sự kiện cho cây. Bộ xử lý sự kiện là một đối tượng thực thi giao diện TreeSelectionListener.
  • Trong bộ xử lý sự kiện thì ta xác định xem nút nào đã được chọn bằng cách là gọi phương thức getLastSelectedPathComponent của cây.
  • Sử dụng phương thức getUserObject để lấy dữ liệu liên quan đến nút đó.

Tùy chỉnh sự hiển thị của một cây

Hình ảnh dưới đây thể hiện một số loại nút được tạo bằng Java, Windows và Mac OS thực thi look and feel.

TreeDemo with angled lines A tree in the Windows look and feel A tree in the MacOS look and feel
Java look and feel Windows look and feel Mac OS look and feel

Như thể hiện ở hình thì ta thấy rằng mỗi một cây ở một nền tảng khác nhau sẽ thể hiện kiểu icon và text khác nhau.

Thông thường mỗi một cây sẽ thực hiện một số thao tác vẽ look-and-feel-specific để chỉ ra mối quan hệ giữa các nút. Ta có thể tùy chỉnh việc vẽ này bằng cách như sau: trước tiên ta sử dụng tree.setRootVisible(true) để hiện nút gốc hoặc tree.setRootVisible(false) để ẩn nó; sau đó ta có thể sử dụng phương thức tree.setShowsRootHandles(true) để yêu cầu các nút mức top (nút gốc nếu nó hiển thị hoặc các nút con của gốc nếu gốc không hiển thị) mở rộng hoặc thu hẹp.

Nếu ta sử dụng Java look and feel thì ta có thể tùy chỉnh các dòng để thể hiện mối quan hệ giữa các nút của cây. Mặc định thì Java look and feel sẽ vẽ các đường chéo góc giữa các nút. Bằng cách thiết lập thuộc tính client JTree.lineStyle của cây, ta có thể chỉ định một quy ước riêng. Ví dụ, để yêu cầu Java look and feel chỉ sử dụng các đường nằm ngang để nhóm các nút thôi thì ta sử dụng câu lệnh sau:

tree.putClientProperty("JTree.lineStyle", "Horizontal");

Còn để xác chỉ định rằng Java look and feel không cần phải vẽ các đường thì ta sử dụng câu lệnh sau:

tree.putClientProperty("JTree.lineStyle", "None");

Hình sau đây thể hiện kết quả khi ta thiết lập các giá trị khác nhau cho thuộc tính JTree.lineStyle đối với Java look and feel:

TreeDemo with angled lines

TreeDemo with horizontal lines

TreeDemo with no lines

"Angled" (mặc định) "Horizontal" "None"

Như ở các hình trên bạn cũng thấy là các biểu tượng icon của mỗi nút gốc hay cành hay lá là những biểu tượng mặc định. Tuy nhiên bạn cũng có thể thay đổi những icon mặc định bằng những icon mà bạn muốn ở cả nút gốc cũng như cành và lá. Cách thức thực hiện là, trước tiên ta tạo một thể hiện của lớp DefaultTreeCellRenderer; bước kế tiếp là ta chỉ định biểu tượng dùng để thay thế bằng cách gọi phương thức tương ứng sau đây: setLeafIcon (dùng cho nút lá), setOpenIcon (dùng cho nút nhánh mở rộng), setClosedIcon (dùng cho nút nhánh thu hẹp). Nếu ta không muốn hiển thị icon cho một nút nào đó thì ta chỉ định null cho icon đó. Sau cùng ta sử dụng phương thức setCellRenderer để chỉ định việc vẽ các nút. Đoạn mã dưới đây là một ví dụ trích từ ví dụ TreeIconDemo:

ImageIcon leafIcon = createImageIcon("public/images/article/middle.gif");
if (leafIcon != null) {
    DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
    renderer.setLeafIcon(leafIcon);
    tree.setCellRenderer(renderer);
}

Hình dưới đây thể hiện sự hiển thị của ví dụ TreeIconDemo:

TreeIconDemo

Nếu bạn muốn kiểm soát tốt hơn qua các biểu tượng nút hoặc bạn muốn cung cấp các tool tip thì bạn có thể thực hiện bằng cách tạo một lớp con của lớp DefaultTreeCellRenderer và ghi đè phương thức getTreeCellRendererComponent. Do DefaultTreeCellRenderer là một lớp con của JLabel nên ta có thể sử dụng bất kỳ phương thức nào của JLabel (như setIcon chẳng hạn) để tùy chình DefaultTreeCellRenderer.

Đoạn mã sau đây trích từ ví dụ TreeIconDemo2, đoạn mã này tạo một bộ kết xuất ô các icon lá khác nhau phụ thuộc vào từ "Tutorial" nằm ở trong text data nào của nút. Bộ kết xuất cũng sẽ chỉ định tool-tip như thể hiện ở dòng lệnh in đậm.

 

//...nơi cây được khởi tạo:
    //Cho phép tool tip.
    ToolTipManager.sharedInstance().registerComponent(tree);

    ImageIcon tutorialIcon = createImageIcon("public/images/article/middle.gif");
    if (tutorialIcon != null) {
        tree.setCellRenderer(new MyRenderer(tutorialIcon));
    }
...
class MyRenderer extends DefaultTreeCellRenderer {
    Icon tutorialIcon;

    public MyRenderer(Icon icon) {
        tutorialIcon = icon;
    }

    public Component getTreeCellRendererComponent(
                        JTree tree,
                        Object value,
                        boolean sel,
                        boolean expanded,
                        boolean leaf,
                        int row,
                        boolean hasFocus) {

        super.getTreeCellRendererComponent(
                        tree, value, sel,
                        expanded, leaf, row,
                        hasFocus);
        if (leaf && isTutorialBook(value)) {
            setIcon(tutorialIcon);
            setToolTipText("This book is in the Tutorial series.");
        } else {
            setToolTipText(null); //không tool tip
        } 

        return this;
    }

    protected boolean isTutorialBook(Object value) {
        DefaultMutableTreeNode node =
                (DefaultMutableTreeNode)value;
        BookInfo nodeInfo =
                (BookInfo)(node.getUserObject());
        String title = nodeInfo.bookName;
        if (title.indexOf("Tutorial") >= 0) {
            return true;
        }

        return false;
    }
}

Hình dưới đây là kết quả của đoạn mã trên:

TreeIconDemo2

Có thể bạn muốn tìm hiểu cách hoạt động của cell renderer. Mỗi khi cây vẽ một nút thì có thể có hoặc không việc JTree thực hiện look-and-feel-specific của nó thực sự chứa đoạn mã dùng để vẽ nút. Thay vào đó, cây sẽ sử dụng mã lệnh vẽ của cell renderer để vẽ nút. Ví dụ như để vẽ nút lá có chuỗi "The Java Programming Language" thì cây yêu cầu cell renderer của nó trả về một thành phần có thể vẽ nút lá với chuỗi đó. Nếu cell renderer là một DefaultTreeCellRenderer thì nó sẽ trả về một nhãn để vẽ biểu tượng nút là mặc định theo sau bởi chuỗi.

Cell renderer chỉ có nhiệm vụ vẽ, nó không thể xử lý sự kiện. Nếu ta muốn thêm xử lý sự kiện cho cây thì ta cần đăng ký bộ xử lý sự kiện cho cây đó, hoặc nếu việc xử lý chỉ xảy ra khi một nút được chọn thì ta sử dụng cell editor của cây.

Thay đổi động một cây

Hình dưới đây thể hiện một ứng dụng gọi là DynamicTreeDemo cho phép bạn thêm và xóa các nút của cây. Ta cũng có thể sửa text trong mỗi nút.

DynamicTreeDemo

Đây là đoạn mã khởi tạo cây:

rootNode = new DefaultMutableTreeNode("Root Node");
treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new MyTreeModelListener());

tree = new JTree(treeModel);
tree.setEditable(true);
tree.getSelectionModel().setSelectionMode
        (TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);

Bằng cách tạo tường minh model của cây, đoạn mã trên đảm bảo rằng model của cây là một thể hiện của DefaultTreeModel. Bằng cách đó thì ta sẽ biết tất cả các phương thức mà model cây hỗ trợ. Ví dụ như ta có thể gọi phương thức insertNodeInto của mô hình mặc dù là phương thức này không được giao diện TreeModel yêu cầu.

Để tạo text có thể sửa trong nút của cây thì ta gọi phương thức setEditable(true) của cây. Khi người dùng sửa xong một nút thì model sẽ tạo một sự kiện model cây để báo cho các bộ lắng nghe của JTree rằng nút có sự thay đổi. Lưu ý rằng mặc dù DefaultMutableTreeNode có phương thức cho phép thay đổi nội dung của nút thì những thay đổi này phải thông qua phương thức của lớp DefaultTreeModel. Nhưng điều này sẽ dẫn đến các sự kiện model cây sẽ không được tạo, và bộ lắng nghe cũng sẽ không biết về sự cập nhật này.

Để thông báo về sự thay đổi của các nút thì ta có thể thực thi TreeModelListener. Đây là một ví dụ về bộ lắng nghe model để nhận diện khi người dùng điền một tên mới cho nút của cây:

class MyTreeModelListener implements TreeModelListener {
    public void treeNodesChanged(TreeModelEvent e) {
        DefaultMutableTreeNode node;
        node = (DefaultMutableTreeNode)
                 (e.getTreePath().getLastPathComponent());

        /*
         * Nếu là các sự kiện của con thì nút đã thay đổi
         * là con của nút mà ta đã chọn. Nếu không thì
         * nút đã thay đổi và nút được chỉ định tương tự nhau.
         */

        try {
            int index = e.getChildIndices()[0];
            node = (DefaultMutableTreeNode)
                   (node.getChildAt(index));
        } catch (NullPointerException exc) {}

        System.out.println("The user has finished editing the node.");
        System.out.println("New value: " + node.getUserObject());
    }
    public void treeNodesInserted(TreeModelEvent e) {
    }
    public void treeNodesRemoved(TreeModelEvent e) {
    }
    public void treeStructureChanged(TreeModelEvent e) {
    }
}

Dưới đây là đoạn mã mà bộ xử lý sự kiện của nút lệnh Add dùng để thêm một nút mới cho cây:

treePanel.addObject("New Node " + newNodeSuffix++);
...
public DefaultMutableTreeNode addObject(Object child) {
    DefaultMutableTreeNode parentNode = null;
    TreePath parentPath = tree.getSelectionPath();

    if (parentPath == null) {
        //Nếu không có nút nào được chọn thì mặc định nút gốc được chọn.
        parentNode = rootNode;
    } else {
        parentNode = (DefaultMutableTreeNode)
                     (parentPath.getLastPathComponent());
    }

    return addObject(parentNode, child, true);
}
...
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                        Object child,
                                        boolean shouldBeVisible) {
    DefaultMutableTreeNode childNode =
            new DefaultMutableTreeNode(child);
    ...
    treeModel.insertNodeInto(childNode, parent,
                             parent.getChildCount());

    //Cần đảm bảo rằng người dùng có thể xem nút mới dễ dàng.
    if (shouldBeVisible) {
        tree.scrollPathToVisible(new TreePath(childNode.getPath()));
    }
    return childNode;
}

Đoạn mã trên sẽ tạo một nút rồi đưa nó vao model của cây, sau đó nếu phù hợp thì nó sẽ yêu cầu các nút ở phía trên nó được mở rộng và cây sẽ được cuộn, lúc này nút sẽ xuất hiện. Để chèn nút vào model thì đoạn mã sử dụng phương thức insertNodeInto được cung cấp bởi lớp DefaultTreeModel.

Tạo mô hình dữ liệu

Nếu DefaultTreeModel không đáp ứng được nhu cầu của ta thì ta sẽ cần tạo một mô hình dữ liệu tùy chỉnh. Mô hình dữ liệu này phải thực thi giao diện TreeModelTreeModel sẽ chỉ định những phương thức dùng để lấy nút cho cây, lấy số con của nút đó, xác định nút lá, thông báo cho mô hình về sự thay đổi trong cây, và thêm hoặc xóa bộ lằng nghe cho mô hình của cây.

Có điều thú vị là giao diện TreeModel chấp nhận bất kỳ loại đối tượng nào là nút của cây. Nó không yêu cầu các nút phải được thể hiện bằng các đối tượng của DefaultMutableTreeNode, hoặc thậm chí là những nút thực thi giao diện TreeNode. Vì vậy, nếu giao diện TreeNode không phù hợp với model cây thì ta có thể tạo ra nút cây riêng theo ý bạn. Ví dụ như nếu bạn có cấu trúc dữ liệu  phân cấp thì bạn không cần phải lặp lại nó hay phân cấp nó vào TreeNode. Bạn chỉ cần thực thi model cây để nó sử dụng thông tin trong cấu trúc dữ liệu của bạn.

Hình dưới đây thể hiện một ứng dụng gọi là GenealogyExample dùng để hiển thị con cháu hay tổ tiên của một người cụ thể.

 

GenealogyExample

Dó model được thực thi như là lớp con Object thay thế, nên có thể nói rằng lớp con của DefaultTreeModel phải thực thi giao diện TreeModel trực tiếp. Yêu cầu này thực thi các phương thức để lấy thông tin về các nút, như là nút gốc và những nút con của một nút cụ thể. Trong trường hợp ví dụ GenealogyModel thì mỗi nút được đại diện bởi một đối tượng có kiểu Person, một lớp tùy chỉnh không thực thi TreeNode.

Model cây cũng phải thực thi những phương thức để thêm và xóa các bộ lắng nghe của model cây, và phải kích hoạt TreeModelEvents tới những bộ lắng nghe đó khi cấu trúc của cây hay dữ liệu thay đổi. Ví dụ, khi người dùng sử dụng ví dụ GenealogyExample thì nó sẽ chuyển từ hiển thị tổ tiên tới hiển thị con cháu, model cây sẽ thực hiện sự thay đổi và kích hoạt một sự kiện để thông báo cho bộ lắng nghe của nó.

Cách nạp Children Lazily

Lazy loading là một đặc điểm của một ứng dụng khi việc nạp và cài đặt thực tế một lớp bị trễ cho tới thời điểm ngay trước khi thể hiện thực sự được sử dụng.

Ta có thể làm bất kỳ điều gì bằng cách tải chúng theo hình thức lazily không? Câu trả lời là có, điều này chắc chắn sẽ tăng hiệu năng của ứng dụng. Bằng cách sử dụng lazily loading ta có thể chỉ định tài nguyên bộ nhớ để nạp và thể hiện hóa một đối tượng chỉ khi nó thực sự được sử dụng. Cách thức này cũng làm tăng tốc độ nạp khởi động của một ứng dụng.

Một trong những cách mà ta có thể sử dụng lazily load cho các con của cây là bằng cách sử dụng interface TreeWillExpandListener. Ví dụ như ta có thể khai báo và tải gốc của cây, ông và cha của cây Tree cùng với ứng dụng như được thể hiện ở đoạn mã dưới đây:

Ta khai báo gốc, ông cha như sau:

class DemoArea extends JScrollPane
                   implements TreeWillExpandListener {
        .......
        .......

        private TreeNode createNodes() {
            DefaultMutableTreeNode root;
            DefaultMutableTreeNode grandparent;
            DefaultMutableTreeNode parent;

            root = new DefaultMutableTreeNode("San Francisco");

            grandparent = new DefaultMutableTreeNode("Potrero Hill");
            root.add(grandparent);

            parent = new DefaultMutableTreeNode("Restaurants");
            grandparent.add(parent);

            dummyParent = parent;
            return root;
        }

Ta có thể nạp những nút được khai báo ở trên tới cây như thể hiện ở đoạn mã sau:

TreeNode rootNode = createNodes();
tree = new JTree(rootNode);
tree.addTreeExpansionListener(this);
tree.addTreeWillExpandListener(this);
.......
.......
setViewportView(tree);

Bây giờ, ta có thể nạp children lazily tới ứng dụng mỗi khi nút cha Restaurants xuất hiện trong ứng dụng. Để làm điều này thì ta khai báo một phương thức phân tách và gọi phương thức đó như thể hiện ở đoạn mã sau:

private void LoadLazyChildren(){
            DefaultMutableTreeNode child;
            child = new DefaultMutableTreeNode("Thai Barbeque");
            dummyParent.add(child);
            child = new DefaultMutableTreeNode("Goat Hill Pizza");
            dummyParent.add(child);
            textArea.append(" Thai Barbeque and Goat Hill Pizza are loaded lazily");
        }

        .......
        .......

public void treeWillExpand(TreeExpansionEvent e)
                    throws ExpandVetoException {
            saySomething("You are about to expand node ", e);
            int n = JOptionPane.showOptionDialog(
                this, willExpandText, willExpandTitle,
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE,
                null,
                willExpandOptions,
                willExpandOptions[1]);

        LoadLazyChildren();
        }

API Tree

Lớp/Interface Mục đích
Lớp và interface liên quan đến Tree
JTree Thành phần dùng để thể hiện cây cho người dùng.
TreePath Đại diện đường dẫn tới một nút.
TreeNode
MutableTreeNode
DefaultMutableTreeNode
Interface mà mô hình cây mặc định mong muốn các nút cây của nó thực thi, và sự thực thi được sử dụng bởi model cây mặc định.
TreeModel
DefaultTreeModel
Tương ứng với interface mà model cây phải thực thi và thực thi mặc định.
TreeCellRenderer
DefaultTreeCellRenderer
Tương ứng với nterface mà cell renderer cây phải thực thi và thực thi mặc định.
TreeCellEditor
DefaultTreeCellEditor
Tương ứng với interface mà cell editor cây phải thực thi và thực thi mặc định.
TreeSelectionModel
DefaultTreeSelectionModel
Tương ứng với interface mà model chọn của cây phải thực thi và thực thi mặc định.
TreeSelectionListener
TreeSelectionEvent
Interface và kiểu sự kiện dùng để phát hiện sự thay đổi của cây đã chọn.
TreeModelListener
TreeModelEvent
Interface và kiểu sự kiện dùng để phát hiện sự thay đổi của model cây.
TreeExpansionListener
TreeWillExpandListener
TreeExpansionEvent
Những interface và kiểu sự kiện dùng để phát hiện sự mở rộng và thu gọn của cây.
ExpandVetoException Một ngoại lệ mà TreeWillExpandListener có thể ném để chỉ ra rằng việc mở rộng lần kế tới không nên xảy ra.

 

Hàm tạo hoặc phương thức Mục đích
Tạo và thiết lập cho cây
JTree(TreeNode)
JTree(TreeNode, boolean)
JTree(TreeModel)
JTree()
JTree(Hashtable)
JTree(Object[])
JTree(Vector)
Tạo một cây. Đối số TreeNode dùng để chỉ định nút gốc, nó được quản lý bởi model cây mặc định. Đối số TreeModel dùng để chỉ định model sẽ cung cấp dữ liệu cho bảng. Phiên bản hàm tạo không đối số được dùng cho các nhà phát triển, nó tạo một cây chứa một số dữ liệu mẫu. Nếu bạn chỉ định một Hashtable, mảng các đối tượng hoặc một Vector làm đối số thì đối số sẽ được đối xử như là một danh sách các nút nằm phía dưới gốc cây (không được hiển thị), và mỗi model và các nút của cây sẽ được tạo một cách phù hợp.

Đối số boolean nếu có sẽ được dùng để chỉ định cách cây cần xác định một nút có được hiển thị như là một lá hay không. Nếu giá trị là false (mặc định) thì bất kỳ nút nào ngoài các nút con đều được hiển thị như là nút lá. Nếu đối số là true thì nút là nút là chỉ khi phương thức itsgetAllowsChildren trả về false.

void setCellRenderer(TreeCellRenderer) Thiết lập renderer để vẽ từng nút.
void setEditable(boolean)
void setCellEditor(TreeCellEditor)
Phương thức thứ nhất dùng để thiết lập việc cho phép người dùng có được chỉnh sửa nút của cây hay không, mặc định là có. Phương thức thứ hai dùng để thiết lập các tùy chỉnh cho trình soạn thảo để sử dụng.
void setRootVisible(boolean) Cho phép cây hiện nút gốc hay không, mặc định là false nếu cây được tạo sử dụng một trong các hàm tạo chứa một cấu trúc dữ liệu, true nếu ngược lại.
void setShowsRootHandles(boolean) Cây có hiển thị các xử lý cho nút tận cùng bên trái nó hay không, cho phép mở rộng và thu gọn hay không. Mặc định là false. Nếu cây không hiển thị nút gốc thì ta nên setShowsRootHandles(true).
void setDragEnabled(boolean)
boolean getDragEnabled()
Thiết lập hoặc lấy thuộc tính dragEnabled, đối số phải chứa giá trị true để cho phép xử lý kéo trên thành phần. Mặc định là false.

 

Thực thi các lựa chọn
Phương thức Mục đích
void addTreeSelectionListener(TreeSelectionListener) Đăng ký một bộ lắng nghe để phát hiện nút được chọn hay không được chọn.
void setSelectionModel(TreeSelectionModel)
TreeSelectionModel getSelectionModel()
Thiết lập hoặc lấy model đã được dùng để điều khiển các nút đã được chọn. Ta có thể tắt nút đã được chọn bằng cách sử dụng phương thức setSelectionModel(null).
void setSelectionMode(int)
int getSelectionMode()
(trong TreeSelectionModel)
Thiết lập hoặc lấy mode được chọn. Giá trị có thể là CONTIGUOUS_TREE_SELECTION, DISCONTIGUOUS_TREE_SELECTION, hoặc SINGLE_TREE_SELECTION (chúng đều được định nghĩa trong TreeSelectionModel).
Object getLastSelectedPathComponent() Lấy đối tượng đại điện cho nút đang được chọn. Điều này tương đương với việc gọi phương thức getLastPathComponent với giá trị trả về bởi tree.getSelectionPath().
void setSelectionPath(TreePath)
TreePath getSelectionPath()
Thiết lập hoặc lấy đường dẫn cho nút đang được chọn.
void setSelectionPaths(TreePath[])
TreePath[] getSelectionPaths()
Thiết lập hoặc lấy những đường dẫn cho những nút đã được chọn.

 

Phương thức Mục đích
Ẩn và hiện các nút
void addTreeExpansionListener(TreeExpansionListener)
void addTreeWillExpandListener(TreeWillExpandListener)
Đăng ký một bộ lắng nghe để phát hiện các nút của cây hiện tại có được mở rộng hay thu gọn, hay sẽ mở rộng hoặc thu gọn. Để ngăn chặn việc mở rộng hay thu hẹp thì ta cho TreeWillExpandListener ném ra aExpandVetoException.
void expandPath(TreePath)
void collapsePath(TreePath)
Mở rộng hoặc thu hẹp đường dẫn của cây.
void scrollPathToVisible(TreePath) Đảm bảo rằng nút được chỉ định bởi đường dẫn sẽ hiển thị - đường dẫn dẫn đến nó được mở rộng và nút nằm trong khu vực quan sát của scroll pane.
void makeVisible(TreePath) Đảm bảo rằng nút được chỉ định bởi đường dẫn là có thể thấy được - đường dẫn dẫn đến nó được mở rộng. Nút có thể không nằm trong vùng nhìn thấy.
void setScrollsOnExpand(boolean)
boolean getScrollsOnExpand()
Thiết lập hoặc lấy thanh cuộn cho cây khi mở rộng cây. Giá trị mặc định của đối số la true.
void setToggleClickCount(int)
int getToggleClickCount()
Thiết lập hoặc lấy số lần click chuột trước khi mở rộng hoặc thu gọn nút. Mặc định là 2.
TreePath getNextMatch(String, int, Position.Bias) Trả về TreePath cho phần tử cây tiếp theo bắt đầu bằng tiền tố được chỉ định.

Ví dụ sử dụng Tree

» Tiếp: Cách sử dụng HTML trong Swing Component
« Trước: Cách sử dụng Tool Tip
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!