Xây dựng cấu trúc cây trong Java Swing với JTree

JTree là một thành phần Swing hiển thị dữ liệu phân cấp, nó là một component khá phức tạp với một nút cha được xem là cha cuả tất cả các node con trong cấu trúc cây. Một nút là một phần tử trong một cây. Một nút có thể có nhiều nút con. Bản thân các nút con này có thể có các nút con khác. Nếu một nút không có bất kỳ nút con nào, nó được gọi là nút lá.

Khởi tạo JTree

Bây giờ chúng ta hãy cố gắng xây dựng một JTree đơn giản. Giả sử chúng tôi muốn hiển thị danh sách các loại rau(vegetables) và trái cây(fruits) theo thứ bậc. Nút được đại diện trong Swing API dưới dạng TreeNode, là một interface.  MutableTreeNode interface thừa kế TreeNode đại diện cho một nút có thể thay đổi được. API Swing cung cấp một triển khai của giao diện này ở dạng lớp DefaultMutableTreeNode.

Chúng ta sẽ sử dụng lớp DefaultMutableTreeNode để đại diện cho nút. Lớp này được cung cấp trong API Swing và chúng ta có thể sử dụng nó để đại diện cho các nút của mình.

Vì vậy, trước tiên chúng ta sẽ tạo nút gốc. Và sau đó chúng ta có thể thêm đệ quy các nút vào gốc đó. Hãy để chúng tôi bắt đầu với một gốc đơn giản chỉ với 2 nút

import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
class TreeExample extends JFrame
{
    private JTree tree;
    public TreeExample()
    {
        //create the root node
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
        //create the child nodes
        DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
        DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
        //add the child nodes to the root node
        root.add(vegetableNode);
        root.add(fruitNode);

        //create the tree by passing in the root node
        tree = new JTree(root);
        add(tree);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("JTree Example");
        this.setLocationRelativeTo(null);
        this.setSize(300, 100);
        this.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TreeExample();
            }
        });
    }
}

Output

Thêm nút vào JTree

Mỗi nút đều có thể thêm các nút con của nó vào bằng cách sử dụng add() method.

import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
class TreeExample extends JFrame
{
    private JTree tree;
    public TreeExample()
    {
        //create the root node
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
        //create the child nodes
        DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
        vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
        vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
        vegetableNode.add(new DefaultMutableTreeNode("Tomato"));
        vegetableNode.add(new DefaultMutableTreeNode("Potato"));
        DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
        fruitNode.add(new DefaultMutableTreeNode("Banana"));
        fruitNode.add(new DefaultMutableTreeNode("Mango"));
        fruitNode.add(new DefaultMutableTreeNode("Apple"));
        fruitNode.add(new DefaultMutableTreeNode("Grapes"));
        fruitNode.add(new DefaultMutableTreeNode("Orange"));
        //add the child nodes to the root node
        root.add(vegetableNode);
        root.add(fruitNode);

        //create the tree by passing in the root node
        tree = new JTree(root);
        add(tree);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("JTree Example");
        this.setLocationRelativeTo(null);
        this.setSize(300, 300);
        this.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TreeExample();
            }
        });
    }
}

Output

Thêm JScrollPane vào JTree

Có vẽ một component như JTree có thể chứa rất nhiều nút dữ liệu, vì vậy khả năng cao là kích thước của JFrame bên ngoài sẽ không thể đáp ứng đủ. Vì vậy chúng ta có thể sử dụng JScrollPane để tạo thanh cuộn cho JTree khi nó chứa quá nhiều nút.

Để thêm JScrollPane cho JTree chúng ta chỉ cần bọc bên ngoài JTree một JScrollPane như sau:

add(new JScrollPane(tree));

Để thanh cuộn xuất hiện khi chúng ta bung các nút con thì mình sẽ giảm kích thước JFrame đi một chút. Mã nguồn đầy đủ như sau:

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
class TreeExample extends JFrame
{
    private JTree tree;
    public TreeExample()
    {
        //create the root node
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
        //create the child nodes
        DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
        vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
        vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
        vegetableNode.add(new DefaultMutableTreeNode("Tomato"));
        vegetableNode.add(new DefaultMutableTreeNode("Potato"));
        DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
        fruitNode.add(new DefaultMutableTreeNode("Banana"));
        fruitNode.add(new DefaultMutableTreeNode("Mango"));
        fruitNode.add(new DefaultMutableTreeNode("Apple"));
        fruitNode.add(new DefaultMutableTreeNode("Grapes"));
        fruitNode.add(new DefaultMutableTreeNode("Orange"));
        //add the child nodes to the root node
        root.add(vegetableNode);
        root.add(fruitNode);

        //create the tree by passing in the root node
        tree = new JTree(root);
        add(new JScrollPane(tree));

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("JTree Example");
        this.setLocationRelativeTo(null);
        this.setSize(300, 200);
        this.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TreeExample();
            }
        });
    }
}

Output

Ẩn root node trong JTree

Để ẩn nút cha trong JTree chúng ta có thể sử dụng tree.setRootVisible(false);

Hiển thị nút đóng/mở rộng trong root node

Nếu các bạn để ý nảy giờ thì nút cha không có nút mũi tên đóng mở. Để thêm đóng mở vào nút cha chúng ta có thể sử dụng setShowsRootHandles(true)

Xử lý sự kiện trong JTree

Chúng ta cần thêm một TreeSelectionListener để lắng nghe các sự kiện lựa chọn. Đây là một giao diện được định nghĩa trong API Swing và chúng ta cần triển khai phương thức valueChanged (). Nguồn của vùng chọn được chuyển làm tham số cho phương thức này.

Việc lựa chọn trong JTree được xử lý bởi một lớp có tên là TreeSelectionModel. Vì vậy, JTree ủy thác tất cả các công việc liên quan đến lựa chọn cho lớp này.

Đầu tiên chúng ta sẽ thêm một JLabel sẽ được hiển thị ở dưới cùng. Bất cứ khi nào một nút trong cây được chọn, chúng tôi sẽ hiển thị đường dẫn của nút đã chọn.

Để thêm xử lý sự kiện vào JTree chúng ta sẽ sử dụng tree.getSelectionModel().addTreeSelectionListener() method.

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;

class TreeExample extends JFrame {
    private JTree tree;
    private JLabel selectedLabel;

    public TreeExample() {
        //create the root node
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
        //create the child nodes
        DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
        vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
        vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
        vegetableNode.add(new DefaultMutableTreeNode("Tomato"));
        vegetableNode.add(new DefaultMutableTreeNode("Potato"));
        DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
        fruitNode.add(new DefaultMutableTreeNode("Banana"));
        fruitNode.add(new DefaultMutableTreeNode("Mango"));
        fruitNode.add(new DefaultMutableTreeNode("Apple"));
        fruitNode.add(new DefaultMutableTreeNode("Grapes"));
        fruitNode.add(new DefaultMutableTreeNode("Orange"));
        //add the child nodes to the root node
        root.add(vegetableNode);
        root.add(fruitNode);

        //create the tree by passing in the root node
        tree = new JTree(root);
        add(new JScrollPane(tree));
        tree.setShowsRootHandles(true);

        tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent e) {
                selectedLabel.setText(e.getPath().toString());
            }
        });

        // Add label to jframe
        selectedLabel = new JLabel();
        add(selectedLabel, BorderLayout.SOUTH);

        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setTitle("JTree Example");
        this.setLocationRelativeTo(null);
        this.setSize(300, 200);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TreeExample();
            }
        });
    }
}

Nguồn tham khảo

https://www.codejava.net/java-se/swing/jtree-basic-tutorial-and-examples

http://www.java2s.com/Tutorials/Java/Java_Swing/1200__Java_Swing_JTree.htm

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x