Cấu trúc cây TREE

1. Cây đơn giản

Giống như hầu hết các thành phần khác của javax. swing, JTree được tổ chức theo mẫu điều khiển. Ta chì cần cung cấp mô hình dữ liệu phân cấp, thành phần này sẽ hiển thị chủng theo cấu trúc cây cho chúng ta. Để tạo ra JTree, ta sử dụng mô hình cây

Vấn đề đặt ra là làm thế nào tạo ra được mô hình cây? Phần sau chúng ta sẽ đề cập đến cách xây dựng lớp mô hình cây riêng trên cơ sờ cài đặt giao diện TreeModel. Ở đầy, để đơn giản ta có thể áp dụng DefaultTreeModel trong j avax . swing để tạo ra mô hình cây vón nút gốc là ro*ot theo giao diện TreeNode.

TreeNode root = …

DefaultTreel^odel model = new DefaultTreetỊodel (root) ;

Để lưu một đối tượng cụ thể ở một nút của cây ta sử dụng DefaultMutableTreeNode. Lớp này cài đặt giao diện MutableTreeNode như hình 4.2.

Ta có thể đưa các đối tượng vào trong toán tử tạo lập của Def aultMutableTreeNode hoặc sử dụng phương thức setUserObject 0 . Ví dụ đặt obj vào node:

DefaultMntableTreeNode node = new DefaultMutableTreeNode (objl) ; node. setUserCfoject (obj2); //Đặt tiếp obj 2 vào node

// Simplexree.java Tạo lập cây mục lục của một cuốn sách

import java.awt.*; import java.awt.event.*; import j avax.swing.*; import javax.swing.tree.*;

public class SimpleTree{

public static void main(String args[]){

JFrame fr = new SimpleTreeFrame(); fr.showO ;

}

}

class SimpleTreeFrame extends JFrame{ public SimpleTreeFrame(){

setTitle(“Content of Java Programming”); setsize(300, 200);

addWindowListener(new WindowAdapter(){

public void windowclosing(WindowEvent e){

System.exit(0) ;

}

});

// Thiết lập mô hình dữ liệu cây phân cấp

DefaultMutableTreeNode root

– new DefaultMutableTreeNode(“Java Programming”);

DefaultMutableTreeNode chapterl

= new DefaultMutableTreeNode(“Multithreading”);

root.add(chapterl);

DefaultMutableTreeNode titlel

= new DefaultMutableTreeNode(“What are threads?”);

chapterl.add(titlel);

DefaultMutableTreeNode title2

= new DefaultMutableTreeNode(“Thread properties”);

chapterl.add(title2);

DefaultMutableTreeNode chapter2

= new DefaultMutableTreeNode(“Networking”);

root.add(chapter2);

DefaultMutableTreeNode title3

= new DefaultMutableTreeNode(“Connecting to Server”);

Chapter2.add(title3);

DefaultMutableTreeNode title4

= new DefaultMutableTreeNode(“Sending E-mail”);

chapter2.add(title4);

// Tạo lập một cây và đặt nó vào thanh trượt

JTree tree = new JTree(root);

Container contentPane = getContentPane();

contentPane.add(new JScrollPane(tree));

}

}

Khi chạy chương trình trên, cây đầu tiên ta nhìn thấy chi có nút gốc và các nút con trực tiếp của nó là tên các chương. Nếu muốn xem nội dung của chương nào thì phải nhấn vào nút

tương ứng (nút đỏng cỏ đầu nhọn chi sang phai) đề mở cây con thể hiện nội dung cùa chương đó. Sau khi xem xong, muốn trờ về nội dung chính trước đó (đóng lại nút đó) ta nhấn lại nút vừa rồi (nút được mơ có đầu nhọn chi xuống dưới) một lần nữa. Tương tự, ta thực hiện cho mọi cây con giống như đối với nút gốc.

javax swing JTree                                                                                                                                              API

  • JTree (TreeModel model): Tạo lập một cầy từ mô hình cây.
  • JTree(TreeNode root): Tạo lập một cây có gốc là
  • JTree (TreeNode root, boolean asksAllowChildren) : Tạo lập một cây và không cho phép các nút con đến được biểu tượng lá nếu biến

booolean là true.

  • void setShowsRootHandles (boolean b) : Nếu b là true, thì nút gốc có bộ điều khiến cho phép đóng lại hoặc mờ ra xem các cây con của nó.
  • void setRootVisible (boolean b) : Nếu b là true, thì nút gốc được hiển thị, ngược lại nó bị che khuất.

javax.swmg.tree.TreeNode                                                                                        API

  • boolean isLeaf (): Trà lại true nếu nút tương ứng là lá.
  • boolean getAllowsChildren (): Trà lại true nếu nếu nút đó có các nút con.

ịavax.svẢng.tree.MutablttT reeNođe                                                                        API

  • void setUserObject (Object obj ): Đặt đối tượng obj vào nút hiện thời.

javax. swing, tree. DeafultMutabl eTreeNode                                                         Aid

  • DeafultMutableTreeNode(Object obj): Tạo ra một nút bằng đối tượng obj.
  • void add (MutableTreeNode child): Bồ sung nút con child vào nút hiện thời.                                                                                             ‘
  • void setAllowsChildren (boolean b): Nếu b là true thi được phép bổ sung các nút con cho nút đó.

2. Soạn thảo cây và đường đi

Trong cấu trúc cây, nhiều khi đòi hỏi phải bổ sung thêm những nút mới hoặc bỏ đi một số nút, nghĩa là phải soạn thảo lại cây cho phù hợp với bài toán ứng dụng. Ngoài ra, để theo dõi được cấu trúc cùa cây thi phải tìm ra được những nút nào đã được chọn, nghĩa là phải chi ra được đường đi từ gốc đến nút đó. Đường di trong cây là dãy các nút con bắt đầu từ gốc. Đường đi được sừ dụng để xác định các nút trên cây. Trong Swing có lớp TreePath quản lý dãy các tham chiếu đối tượng (không phải là các nút). Khi ta có một đường đi của cây, nếu muốn biết nút cuối cùng thì gọi phương thức getLastPathComponent (), còn nếu muốn biết nút hiện thời có ở trên cây hay không thì sử dụng getSelectionPath ().

Khi một nút được chọn, vi dụ selectedNode, ta có thể thêm, hoặc xoá nút đó. Truy nhiên không thể sử dụng hàm add() để chèn thêm một nút con vào

selectedNode. add (newNode) ;         //Không thực hiện được

Ngược lại, nếu muốn thay đổi cấu trúc của cây thi phải thay đồi cấu trúc của các nút. Ta có thể sữ dụng

model. insertNodelnto (ns4Nbde, selectecNode, selectecNxle. getơiildGơunt ()) ;

để chèn thêm một nút mới như là nút lá vào cây con có gốc là selectedNode theo mô hình cây mặc định model.

Tương tự, ta có thề xoá đi một nút (một cây con) đã chọn

model.removeNodeFromParent(selectedNode);

Ví dụ 4.2. Xây dựng một cấu trúc cây, trên đó thực hiện được các chức năng thêm hoặc loại bò đi một nút (cây con) bất kỳ. Khi đã chọn một nút trong và muốn thêm một nút mới cùng mức với nút đó thi nhấn “Add sibling”, thêm một nút lá cùa cây con thi nhấn “Add Child”, còn muốn xoá nút đó thỉ nhấn “Delete”. Mỗi nút mới được bổ sung vào có tên là “New Node” sau đó có thể nhấn đúp chuột để sửa lại tên của các nút.

/* TreeEdit.java Tạo ra cấu trúc cây và khả nâng chèn thêm, xoá bò đi càc nút như hình 4.4.

*/

import j ava. awt. *; import java.awt.event.*; import j avax.swing.*; import javax.swing.tree.*; public class TreeEdit{

public static void main(String args[]){

JFrame fr = new TreeEditFrame(); fr.show();

}

}

class TreeEditFrame extends JFrame implements ActionListener{ private DefaultTreeModel model; private JTree tree;

private JButton addsiblingButton, addChildButton; private JButton deleteButton, editButton; public TreeEditFrame(){

setTitle(“Tree Editor”); setSize(300, 200);

addWindowListener(new WindowAdapter(){

public void windowclosing(WindowEvent e){

System.exit(0);

}

}) ;

//Xây dựng cây

TreeNode root = makeSampleTree(); model = new DefaultTreeModel(root); tree = new JTree(model); tree.setEditable(true);

// Đưa cây vào thanh cuốn để xem khi chúng vượt quá khuôn khổ khung nhìn

Container content = getContentPane();

JScrollPane scrollPane = new JScrollPane(tree); content.add(scrollPane, “Center”);

// Tạo lập bảng các nút chèn thêm, xoả bỏ các nút JPanel panel = new JPanelO;

addsiblingButton = new JButton(“Add sibling”); addSiblingButton.addActionListener(this); panel.add(addSiblingButton); addChildButton = new JButton(“Add Child”); addChildButton.addActionListener(this); panel.add(addChildButton); deleteButton = new JButton(“delete”);

deleteButton.addActionListener(this); panel.add(deleteButton); content.add(panel, “South”);

}

public TreeNode makeSampleTree(){

DefaultMutableTreeNode root

= new DefaultMutableTreeNode(“Java Programming”); DefaultMutableTreeNode chapterl

= new DefaultMutableTreeNode(“Multithreading”); root.add(chapterl);

DefaultMutableTreeNode titlel

= new DefaultMutableTreeNode(“What are threads?”); chapterl.add(titlel);

DefaultMutableTreeNode title2

= new DefaultMutableTreeNode(“Thread properties”); chapterl.add(title2);

DefaultMutableTreeNode chapter2

= new DefaultMutableTreeNode(“Networking”); root.add(chapter2);

DefaultMutableTreeNode title3

= new DefaultMutableTreeNode(“Connecting to Server”); chapter2.add(title3);

DefaultMutableTreeNode title4

= new DefaultMutableTreeNode(“Sending E-mail”); chapter2.add(title4); return root;

}

public void actionPerformed(ActionEvent event)(

DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if(selectedNode = null) return; if(event.getSource().equals(deleteButton)){ if(selectedNode.getParent{) != null)

model.removeNodeFromParent{selectedNode); return;

}

// Chèn thêm nút mới

DefaultMutableTreeNode newNode

= new DefaultMutableTreeNode(“New Node”); if(event.getSource0.equals(addsiblingButton)){ DefaultMutableTreeNode parent

= (DefaultMutableTreeNode)selectedNode.getParent(); if(parent != null){

int selectedlndex = parent.getIndex(selectedNode); model.insertNbdelnto(newNode, parent, selectedlndex + 1);

}

}else if(event.getSourceO.equals(addChildButton)) model.insertNodelnto(newNode, selectedNode, selectedNode.getChildCount 0);

// Hiển thị nút mới

TreeNodeU nodes = mode 1. getPathToRoot (newNode); TreePath path = new TreePath(nodes); tree.scrollPathToVisible(path);

■ TreePath getSelectionPath (): Xác định đường đi tới nút hiện thời

* Object getLastSelectedComponent (): Xác định đối ‘tượng biểu diễn cho thành phần cùa nút hiện thời (nút được chọn).

  • void makeVisible (TreePath path): Mờ ra để nhìn được tất cả các nút theo đường dẫn.
  • void scrollPathToVisible (TreePath path): Mở các nút theo đường dẫn và nếu cây để trong thanh cuốn thi nó đảm bảo luôn nhìn thấy được những nút cuối.

javax. swing. TreeNode                                                                                                 API

  • TreeNode getParent (): Tỉm nút cha của nút hiện thời.
  • TreeNode getChildAt(int index): Tìm nút con ờ vị trí
  • int getChildCount (): Đếm số nút con của nút hiện thời.

ịavax. swing. DefaultTreeModel                                                                   I                                             AB

  • void insertNodelnto (MutableTreeNode newChild, MutableTreeNode parent, int index): Chèn thêm nút newChild vào như là nút con của parent và ờ vị trí
  • void removeNodeFromParent(MutableTreeNode node): Loại bỏ đi
  • void nodeChanged (TreeNode node): Thông báo cho mô hình cây rằng nút này phải thay đổi.
  • void reload (): Nạp tất cả các nút vào mô hình

3. Đánh số các nút trên cây

Đế tìm một nút trên cây, người ta thường bắt đầu từ gốc sau đó tỉm qua tất cả các nút Đây là vấn để khó, mất nhiều thời gian khi số nút trên cáy là khá lớn. Trong lý thuyết đồ thị, các thuật toán duyệt trên cây có thế thực hiện theo chiều rộng hoặc theo chiều sâu. Lớp De faultMutableTreeNode cũng có một số phưcmg thức khá tiện lợi cho việc đánh số các nút và thực hiện tim lặp lại theo các nút. Phương thức breadthFirstEnumeration() đánh số theo chiều rộng và depthFirstEnumeration () đánh số theo chiều sâu được thực hiện như hình 4.5. Đánh số theo chiều rộng thục hiện theo thuật loán duyệt gốc tnrớc, sau đó duyệt tất cả các nút con của nó. Thuật toán này lặp lại đệ qui cho các nút con của cây. Đánh số theo chiều sâu thực hiện theo thuật toán duyệt gốc sau cùng, duyệt qua tất cả các nút lá, sau đó mới đến nút gốc cùa chúng. Tất nhiên, ở đây già thiết một đối tượng được lặp lại hai lần trên cây.

Ta có thể sử dụng mẫu sau để duyệt cây theo chiều sâu.

Enumeration breadthFirst = node.breadthFirstEnumeration(); while(breadthFirst.hasMoreElement()){

// Thực hiện đối vời breadthFirst. nextElement ()

}

Để tim một đối tượng trên cây, ta có thể sừ dụng phương thức dạng.

public DefaultMutableTreeNode findUserObject(Object obj) { Enumeration e = root.breadthFirstEnumeration(); while(e.hasMoreElement()){

DefaultMutableTreeNode node

= (DefaultMutableTreeNode)e.nextElement(); if(node.getUserObject().equals(obj))

return node;

}

return null;

}

4. Thay đổi biểu diễn các nút của cây

Trong các chương trình ứng dụng ta thường có nhu cầu thay đổi cách vẽ các nút của cây. Một trong những thay đổi hay gặp phải là dùng một biểu tượng khác, phù hợp với bài toán ứng dụng, với trực quan cùa người sừ dụng đề biểu diễn các nút trên cây. Theo mặc định, lóp JTree sử dụng DefaultTreeCellRenderer để vẽ cho các nút. Ta cũng có thể thay đổi lại chúng theo ba cách.

  1. Thay đổi biểu tượng, font chữ và màu nền được sử dụng bời DefaultTreeCellRenderer.
  1. Cài đặt lớp mới kế thừa DefaultTreeCellRenderer để thay đổi biểu tượng, font chữ và màu nền cho mỗi nút.
  2. Xây dựng một lóp cài đặt giao diện TreeCellRenderer để vẽ ảnh cho từng nút cùa cây.

Ví dụ, có ba hình tròn: muốn hình Xíinh biểu diền cho lá, hình đỏ cho nút đóng và hình vàng cho nút mờ, ta có thể làm như sau:

DefaultTreeCellRenderer render

= new DefaultTreelellRenderer(); render.setLeafIcon(new Imagelcon(“blueBall.gif”)); render.setciosedlcon(new ImageIcon(“redBall.gif”)); render.setOpenlcon(new Imagelcon(“yellowBall.gif”)); tree.setCellRenderer(render);

Ví dụ 4.3. Xây dựng cây các lớp kế thừa cùa j ava. lang. Ob j ect, trong đó hình tròn màu xanh biểu diễn cho lá, màu đỏ là nút đóng, còn nút vàng là nút mờ. Ta có thể sứ dụng những hệ soạn thào ảnh như Photoshop để tạo ra các biểu tượng: hình tròn (tương đối nhỏ) với các màu nêu trên. Từ trường văn bản ở phía dưới, ta có thể nhập vào tên các lớp trong thư viện của Java, ví dụ j ava.applet.Applet. Neu lớp đó chưa có trên cây thì nó được bổ sung vào cây theo đúng thứ tự thừa kế giữa các lóp.

Hình 4.6. Câv thừa kế giữa các lớp của Java

// ClassTree.java: Xây dựng cây thừa kế giữa các lớp của Java, import java.awt.*; import java.awt.event.*; import java.util.*; import java.lang.reflect.*; import javax.swing.*; import javax.swing.event.*;

Import javax.swing.tree.*;

public class ClassTree{

public static void main(String argsUH JFrame fr = new ClassTreeFrame(); fr.show();

}

}

class ClassTreeFrame extends JFrame implements

ActionListener{

private DefaultMutableTreeNode root; private DefaultTreeModel model; private JTree tree;

private JTextField textField;

public ClassTreeFrame(){

setTitle(“Rendering tree”); setsize(300, 200);

addWindowListener(new WindowAdapter(){

public void windowclosing(WindowEvent e){ System.exit 10) ;

}

}) ;

// Gốc của cây là java.lang.Object

root = new DefaultMutableTreeNode(java.lang.Object.class); model = new DefaultTreeModel(root); tree = new jTree(model); tree.setEditable(true);

// Bổ sung lớp hiện thời vào cây cùng với dữ liệu addciass(getciass());

/* Đặt thêm các biểu cho các nút: hình xanh cho lả, đỏ cho nút đóng và vàng cho nút mờ

*/

ClassNameTreeCellRender render

= new ClassNameTreeCellRender(); render.setLeaflcon(new Imagelcon(“blueBall.gif”)); render.setclosedlcon(new ImageIcon(“redBall.gif”)); render.setOpenlcon(new ImageIcon(“yellowBall.gif”)); tree.setCellRenderer(render);

Container content = getContentPane();

JScrollPane scrollPane = new JScrollPane(tree); content.add(scrollPane, “Center”);

// Tên các lớp mới đuợc nhập vào từ trường văn bàn. textField = new jTextField(); textField.addActionListener(this); content.add(textField, “South”);

public void actionPerformed(ActionEvent event){

11 Bổ sung thêm lớp mới được nhập vào cây try {

String text = textField.getText (); addClass(Class.forName(text));

// Xoá trường văn bản textField.setText(“”);

}catch(ClassNotFoundException e){

Toolkit.getDefaultToolkit () .beep ();

}

}

// Tìm nút chửa đối tượng của người sử dụng

public DefaultMutableTreeNode findUserObject(Object obj ) { Enumeration e = root.breadthFirstEnumeration(); while(e.hasMoreElements() ) {

DefaultMutableTreeNode node

= (DefaultMutableTreeNode)e.nextElement(); if(node.getUserObj ect() .equals(obj)) return node;

}

return null;

}

public DefaultMutableTreeNode addciass(Class c){

// Bổ sung lớp mới vào cây

if(c.islnterface() II c.isPrimitíve()) return null; // Bò qua những kiểu không phải lóp

DefaultMutableTreeNode node = fIndUserObject(c); if”(node != null) return node;

// Nếu lớp không có thì bổ sung lớp cha vào cây và lặp lại

Class s = c.getSuperclass();

DefaúltMutableTreeNode parent; if (s === null) parent = root; else parent = addciass(s);

// Bổ sung lớp mới nhu là lớp con

DefaultMutableTreeNode newNode = new DefaultMutabl eTreeNode (c); model. insertNodelnto (newNode, parent, parent. getChildCount 0 ) ;

// Cho phép hiểu thị

TreePath path = new TreePath(model.getPathToRoot(newNode)) ; tree.makeVisible(path); return newNode;

}

}

class ClassNameTreeCellRender extends DefaultTreeCellRendereri

public Component getTreeCellRenderComponent(JTree tree, Obj ect value, boolean selected, boolean expanded, boolean leaf, int row,boolean hasFocus){

super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);

// Xác định đối tượng nhập vào

DefaultMutableTreeNode node = (Defaul tMutablelreeNode)value; Class c = (Class)node.getUserObject();

// Lần đầu, đặt font chữ nghiêng thay font chữ chân phương

if (plaintFont == null){ plaintFont = getFontO; if(plaintFont != null)

italicFont = plaintFont.deriveFont(Font.ITALIC);

}

// Đặt font nghiêng nếu lớp là lớp trừu tượng

if((c.getModifiers() & Modifier.ABSTRACT) == 0) setFont(plaintFont);

else

setFont(italicFont); return this;

}

private Font plaintFont; private Font italicFont;

5. Hiển thị thông tin của các nút

Thông thường, mỗi thành phần (nút) của cây được gắn với một thành phần khác. Khi người sừ dụng lụa chọn một số nút trên cây thi những thông tin chứa trên những nút đó có thể được hiển thị ờ cừa sồ bên cạnh. Ví dụ, trên cây thừa kế các lớp của Java, nếu ta chọn j ava. awt. Frame thi các thuộc tính (biến tham chiếu, biến tĩnh) cùa nó được hiển thị ở cửa sổ bên phải như hình 4.7.

Ví dụ 4.4. Chương trình này khác với chương trình trước ở chồ phải xử lý các sự kiện khi người sừ dụng chọn một lớp trên cầy đề xem nó có những thành phần nào. Mồi khi một nút lớp được chọn thì nội dung tương ứng với nó được hiển thị ở cứa số bên cạnh.

Đế xừ lý các sự kiện như thế ta viết thêm

public void valueChanged(TreeSelectionEvent event){

// Bạn chọn các nút khác đề xem các thành phần của lớp

TreePath path = tree.getSelectionPath(); if(path == null) return;

DefaultMutableTreeNode selectedNode

= (DefaultMutableTreeNode)path.getLastPathComponent(); Class c = (Class)selectedNode.getUserObject0; String descr = getFieldDescription(c); textArea.setText(descr) ;

}

Ngoài ra, việc chọn các nút trên cây có thể chọn từng nút hoặc chọn một dãy các nút liền nhau, hoặc càc nủt không liên tục. Cách chọn này được xác định theo mode chọn Lớp JTree sừ dụng TreeeSelectionMode để điều khiển mode chọn bằng cách chọn từng nút là s INGLE_SELECT I ON, hoặc CONTIGUOUS_TREE_SELECTION để chọn liên tục, DISCONTINTIGUOUS_SELECTION (chọn không liên tục là mặc định). Trong ví dụ này ta chọn từng nút (ứng với các lóp) để hiển thị.

int mode = TreeSelectionModel. SINGLE_TBJEE_SELECTION;

Để tỉm được nút hiện thời trên cây, ta truy vấn vào cây qua phương thức

TreePath path = tree.getSelectionPath ();

nhằm tìm ra một đối tượng trên đường dẫn ứng với nút đã được chọn. Ta sử dụng phương thức getFieldDescription (c) để hiển thị các thành phần của lớp c trong vùng vãn bản bên cạnh.

// TreeBrowser.java

import j ava.awt.*; import java.awt.event.* ; import java.util.*; import java.lang.reflect.*; import j avax . swing . * import javax.swing.event.*; import j avax.swing.tree.*;

public class TreeBrowserf

public static void main(String args[]){

JFrame fr = new TreeBrowserFrame(); fr.show();

}

}

class TreeBrowserFrame extends JFrame

implements ActionListener, TreeSelectionListener{

// Các thuộc tính

private DefaultMutableTreeNode root; private DefaultTreeModel model; private JTree tree; private JTextField textField; private JTextArea textArea;

public TreeBrowserFrame(){ setTitle(“Tree Browser”); setsize(300, 200);

addWindowListener(new WindowAdapter(){

public void windowclosing(WindowEvent e){ System.exit(0);

}

});

// Gốc của cây là Object

root = new DefaultMutableTreeNode(java.lang.Object.class); model = new DefaultTreeModel(root); tree = new JTree(model); tree.setEditable(true);

// BỒ sung lớp vào cây cùng với dữ liệu addClass(getciass());

// Đặt mode để chọn

tree.addTreeSelectíonListener(this);

int mode = TreeSelectioriModel.SINGLE_TREE_SELECTION;

tree.getSelectionModel().setSelectionMode(mode);

// Tạo lập vùng để hiền thị văn bàn textArea = new JTextArea();

// Bổ sung vùng văn bản vào panel

JPanel panel = new JPanel();

panel.setLayout(new GridLayout(1, 2));

panel.add(new JScrollPane(tree));

panel.add(new JScrollPane(textArea));

Container content = getContentPane(); content.add(panel, “Center”);

// Nhận tên của các lóp mới từ trường văn bản textField = new JTextField(); textField.addActionListener(this); content.add(textField, “South”);

}

public void actionPerformed(ActionEvent event)! try {

String text = textField.getText (); addciass(Class.forName(text));

//

textFieId.setText(“”);

}catch(ClassNotFoundException e){

Toolkit.getDefaultToolkit().beep();

}

}

public void valueChanged(TreeSelectionEvent event){

// Bạn chọn các nút khác để xem các thành phần của lớp

TreePath path = tree.getSelectionPath(); if(path == null) return;

DefaultMutableTreeNode selectedNode

= (DefaultMutableTreeNode) path.getlastPathCcrrponent () ; Class c = (Class)selectedNode.getUserObject(); String descr = getFieldDescription(c); textArea.setText(descr) ;

}

public DefaultMutableTreeNode findUserObject(Object obj){ // Tìm nút chúa đối tượng của người sử dụng

Enumeration e = root.breadthFirstEnumeration(); while(e.hasMoreElements()){

DefaultMutableTreeNode node

= (DefaultMutableTreeNode)e.nextElement(); if(node.getUserObject().equals(obj)) return node;

}

return null;

}

public DefaultMutableTreeNode addciass(Class c){

// Bỏ qua những kiểu không phải là lớp

if(c.islnterface 0 II c.isPrimitive()) return null; //Tim đối tượng

DefaultMutableTreeNode node = findUserObject(c); if(node != null) return node;

// Nếu lớp đó không có mặt thì bổ sung lớp cha cùa nó và lặp lại

Class s = c.getSuperclass();

DefaultMutableTreeNode parent; i f(s == null) parent = root; else

parent = addciass(s) ;

// BỔ sung lớp mới như là lớp con

DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(c); model. insertNodelnto (newNode, parent, parent.getChildCount ()) ;

// Cho phép hiển thị nút

TreePath path = new TreePath(model.getPathToRoot(newNode)); tree.makeVi sible (path); return newNode;

}

public static String getFieldDescription(Class c){

// Tim kiểu và tên của các trường String r =

Field[] fields = c. getDeclaredFields() ; for(int i = 0; i < fields.length; i++){

Field f = fields[ì];

if((f.getModifiers() & Modifier.STATIC)         != 0)

r += “static

r += f.getType().getName() + ” “; r += f.getName() + “\n”;

}

return r;

}

}