`
sendliu
  • 浏览: 11154 次
社区版块
存档分类
最新评论

jtree02

 
阅读更多
在总结了数人的博客和自己的探索之下,终于实现,其中主要就是TreeCellRenderer这个接口的实现,
下面代码
用的Jcreator,需要在项目文件了加入image文件夹和图片文件。
Test.java

package myprojects.test;

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


public class Test extends JFrame implements TreeSelectionListener{
  JButton addB, deleteB,addBS,addT;
  JTree tree;
  DefaultTreeModel treeModel;
  DefaultMutableTreeNode leadSelection;
  ImageIcon test;
  JLabel label;

    public Test() {
    super("Tree Event Demo");
    setSize(600,400);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

           

    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);
    tree.setExpandsSelectedPaths(true);
    tree.setEditable(true);
    getContentPane( ).add(new JScrollPane(tree), BorderLayout.CENTER);
    tree.addTreeSelectionListener(this);
   
    MyTreeCellRenderer myCellRenderer = new MyTreeCellRenderer(); 
    //设置叶子节点的图标  
    tree.setCellRenderer(myCellRenderer);
   
        //按钮
    addB = new JButton("Add a Child node");
    addBS=new JButton("Add a Sibling node");
    deleteB = new JButton("Delete a node");
    addT=new JButton("Test");
   
    JPanel buttonP = new JPanel( );
    buttonP.add(addB);
    buttonP.add(addBS);
    buttonP.add(deleteB);
    buttonP.add(addT);
    getContentPane( ).add(buttonP, BorderLayout.SOUTH);

    addB.addActionListener(new ActionListener( ) {
        public void actionPerformed(ActionEvent ae) {
          String nodeName = JOptionPane.showInputDialog("New node name:");
          if (leadSelection != null&&nodeName!=null) {
            leadSelection.add(new DefaultMutableTreeNode(nodeName));
            ((DefaultTreeModel)tree.getModel( )).reload(leadSelection);
          }
          else {
            JOptionPane.showMessageDialog(Test.this, "Error! Please select a node and input the nodename");
          }
        }
      });

    addBS.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent ae) {
          String nodeName = JOptionPane.showInputDialog("New node name:");
          if (leadSelection != null&&leadSelection.getParent()!=null&&nodeName!=null) {
            ((DefaultMutableTreeNode)leadSelection.getParent()).add(new DefaultMutableTreeNode(nodeName));//该步骤改为先寻找parent然后加node
            ((DefaultTreeModel)tree.getModel( )).reload(leadSelection.getParent());
          }
          else {
            JOptionPane.showMessageDialog(Test.this, "Error! Please select a node, input the nodename and insure the node is not the root");
          }
        }
    });
   
    deleteB.addActionListener(new ActionListener( ) {
        public void actionPerformed(ActionEvent ae) {
          if (leadSelection != null) {
            DefaultMutableTreeNode parent =
              (DefaultMutableTreeNode) leadSelection.getParent( );
            if (parent == null) {
              JOptionPane.showMessageDialog(Test.this, "Can't delete root");
            }
            else {
              parent.remove(leadSelection);
              leadSelection = null;
              ((DefaultTreeModel)tree.getModel( )).reload(parent);
            }
          }
          else {
            JOptionPane.showMessageDialog(Test.this, "No Selection...");
          }
        }
      });
     
      addT.addActionListener(
          new ActionListener( ) {
        public void actionPerformed(ActionEvent ae) {
            String nodeName = JOptionPane.showInputDialog("New node name:");
            test=new ImageIcon("../image/class.PNG");
            label=new JLabel();
            label.setIcon(test);
            label.setText(nodeName);
          if (leadSelection != null&&nodeName!=null) {
            leadSelection.add(new DefaultMutableTreeNode(label));
            ((DefaultTreeModel)tree.getModel( )).reload(leadSelection);
          }
          else {
            JOptionPane.showMessageDialog(Test.this, "Error! Please select a node and input the nodename");
          }
            }
     });
    }
   
   
   
   
      public void valueChanged(TreeSelectionEvent e) {
    TreePath leadPath = e.getNewLeadSelectionPath( );
    if (leadPath != null) {
      leadSelection = (DefaultMutableTreeNode)leadPath.getLastPathComponent( );
    }
  }


    public static void main(String args[]) {
        //System.out.println("Starting Test...");
        //Test mainFrame = new Test();
        //mainFrame.setSize(400, 400);
        //mainFrame.setTitle("Test");
        //mainFrame.setVisible(true);
            Test te = new Test( );
            te.setVisible(true);

    }
}

Ok,另外MyTreeCellRenderer类的代码如下MyTreeCellRenderer.java
package myprojects.test;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
class MyTreeCellRenderer extends DefaultTreeCellRenderer {
    public Component getTreeCellRendererComponent(JTree tree, Object value,boolean selected, boolean expanded,boolean leaf, int row, boolean hasFocus) {
      
   DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
   Object obj = node.getUserObject();
   if(obj instanceof JLabel) {
        JLabel label = (JLabel)obj;
        DefaultTreeCellRenderer tempCellRenderer = new DefaultTreeCellRenderer();
        tempCellRenderer.setLeafIcon(label.getIcon());
        return  tempCellRenderer.getTreeCellRendererComponent(tree,label.getText(),selected,expanded,true,row,hasFocus);
   }
   return super.getTreeCellRendererComponent(tree,value,
selected,expanded,leaf,row,hasFocus);
   }
}

整个类是gool实现的,我写了个Test用了一下而已,不过作为一个整体,理解起来比较容易。
http://blog.sina.com.cn/s/blog_47e3d38d01000716.html

JTree及JTable的一些“剖析”
1.JTree的显示
最近因为要使用JTree及JTable做一些图片的显示及操作,因为以前都是肤浅的用过,所以并为深入。现在遇到的问题如在JTree里面如何单独显示每个cell的图片,比如在JTable里面如何画出别的控件等!
在网寻求帮助,但效果并不是很好,所以自行研究了一翻,虽然并未象那些资深人士一般做出精辟的真正的剖析,但我相信我的“一些剖析”还是能帮助到一些正在,或者正要使用这两大swing控件的人。
首先来说下JTree,单就显示父节点,子节点的图片是比较简单的,我们用DefaultTreeCellRenderer这个类就能实现。调用setOpenIcon(), setCloseIcon(), setLeafIcon()三个方法,分别实现父节点打开的图片,父节点关闭的图片,以及叶节点的显示图片。然后在相应需要显示的JTree里面调用setCellRenderer(TreeCellRenderer x)即可。至于别的字体,背景色等都在DefaultTreeCellRenderer里面相应的set方面里面,大家可通过JDK自行寻找。
这上面说的方法是极为简单的实现图片的方法,一般也就足够了,但是如果你想在节点里面实现自己的控件或者每个cell都需要拥有自己图片如何操作呢?使用DefaultTreeCellRenderer是不能满足我们的要求的,至少我是没找到简便的方法!因为使用JTree的setCellRenderer(TreeCellRenderer x) 方法后,是使所有cell都使用实现了TreeCellRenderer接口的类,这里我们用的是DefaultTreeCellRenderer来进行显示的.
那么我们先来看看DefaultTreeCellRenderer是如何实现TreeCellRenderer这个接口的:
    public Component getTreeCellRendererComponent(JTree tree, Object value,
        boolean sel,
        boolean expanded,
        boolean leaf, int row,
        boolean hasFocus) {
  String  stringValue = tree.convertValueToText(value, sel,
       expanded, leaf, row, hasFocus);
       this.tree = tree;
  this.hasFocus = hasFocus;
  setText(stringValue);
  if(sel)
      setForeground(getTextSelectionColor());
  else
      setForeground(getTextNonSelectionColor());
  // There needs to be a way to specify disabled icons.
  if (!tree.isEnabled()) {
      setEnabled(false);
      if (leaf) {
   setDisabledIcon(getLeafIcon());
      } else if (expanded) {
   setDisabledIcon(getOpenIcon());
      } else {
   setDisabledIcon(getClosedIcon());
      }
  }
  else {
      setEnabled(true);
      if (leaf) {
    setIcon(getLeafIcon());
      } else if (expanded) {
    setIcon(getOpenIcon());
      } else {
    setIcon(getClosedIcon());
      }
  }
        setComponentOrientation(tree.getComponentOrientation());
   
  selected = sel;
  return this;
    }
以上的橙色部分就是DefaultTreeCellRenderer为节点设置图片的地方,这个类本就是继承JLabel并且实现的TreeCellRenderer接口,所以以上蓝色部分是把传来的value加到Label的文字部分,并且return的是this,也就是标签了。
至于getLeafIcon(),getClosedIcon(),getOpenIcon(),对应得到的值就是我们调用对应的set方法给的值.
了解到这些你是否有想法了?对了,那就是我们自己实现TreeCellRenderer接口。那么我们就能显示自己需要的图片及控件了。但是前提还有个问题需要我们了解,那就是我们的节点—DefaultMutableTreeNode;构造一个节点时可以传任意的一个类,因为构造函数是用Object类来接收的:public DefaultMutableTreeNode(Object userObject) 。所以我们可以直接传入需要的东西,比如我们需要图片加文字,就直接传入Label即可,然后让我们自己实现了TreeCellRenderer的类实现就行了。而不必担心象DefaultTreeCellRenderer一样,标签的Text来源于Node构造时传入的对象的.toString(),而图片来源于事先set的ImageIcon. 这样,我们的JTree就可以多样化了,想要什么东西就传入什么东西,而不必担心他显示不出来。
而我们即将实现的接口public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) ;
着色的形参value是个节点对象,那么这里就需要用到getUserObject()方法来获取我们构造DefaultMutableTreeNode时传入的对象,运用RTTI来识别类型,如果是我们希望的类型就做出处理,否则就象DefaultTreeCellRenderer一样,用默认的ImageIcon加上value.toString来显示.。哦,对了!节点的toString()是重写过的,return getUserObject().toString;这里解释一下一面误会!
一切准备工作搞定,以下就是实现接口的细节了,代码如下:
class MyTreeCellRenderer implements TreeCellRenderer {
    public Component getTreeCellRendererComponent(JTree tree, Object value,boolean selected, boolean expanded,boolean leaf, int row,boolean hasFocus) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
        Object obj = node.getUserObject();
        if(obj instanceof JLabel) {
            return (JLabel)obj;
        }
        if(obj instanceof JCheckBox) {
            return (JCheckBox)obj;
        }
        if(obj instanceof JRadioButton) {
            return (JRadioButton)obj;
        }
        label.setText(value.toString());
        if (leaf)
            label.setIcon(leafIcon);
        else if (expanded)
            label.setIcon(openIcon);
        else
            label.setIcon(closeIcon);
        return label;
      
    }
    public void setOpenIcon (ImageIcon image) {
        openIcon = image;
    }
    public ImageIcon getOpenIcon () {
        return openIcon;
    }
    public void setClosedIcon(ImageIcon image) {
        closeIcon = image;
    }
    public ImageIcon getClosedIcon() {
        return closeIcon;
    }
    public void setLeafIcon(ImageIcon image) {
        leafIcon = image;
    }
    public ImageIcon getLeafIcon() {
        return leafIcon;
    }  
    private JLabel label = new JLabel();
    private boolean flag = true;
    private ImageIcon openIcon = new ImageIcon(".\\src\\image\\open.png");
    private ImageIcon closeIcon = new ImageIcon(".\\src\\image\\close.png");
    private ImageIcon leafIcon = new ImageIcon(".\\src\\image\\buddy.gif");
}
这个类把TreeCellRenderer接口实现了,注意上面着色的部分,我们把自己需要用到的组件直接返回,这样就可以在给构造node的时候直接传过去了。至于一般的图文结合或者是不能识别的类型处理方式和DefaultTreeCellRenderer一样。但是最终实现是实现了,问题也有不少,比如我们选中node后颜色不会变化,让我们无法区分是否选择等等一系列问题,最重要的是如果添加的组件,如何进行组件的操作等!以下给出了解决方案!
其实实现UI细节比较烦琐,因为你传入的控件都有自己的paint()方法,这就说明你如果要实现细节那么必然要重写这些paint()方法来配合JTree显示,既然要重写这些方法那么你所传入的控件至少是从实现了paint()重写方法的类实例化而来,这就是烦琐之处。如果大家有兴趣可以参考DefaultTreeCellRenderer类来自己写这些方法!
我想也可以通过传来的控件一个个set属性也能达到目的,但是这效率就不是很高了。唯一方便的就不用从某个控件派生而来,把共有属性都写到一堆,也不唯是个好办法。
当然DefaultTreeCellRenderer类是继承的JLabel,而我当下要用的无非就是实现每个cell有自己图片而已,所以偷了一个懒,以下是我实现部分的源码。
class MyTreeCellRenderer extends DefaultTreeCellRenderer {
    public Component getTreeCellRendererComponent(JTree tree, Object value,boolean selected, boolean expanded,boolean leaf, int row, boolean hasFocus) {
      
   DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
   Object obj = node.getUserObject();
   if(obj instanceof JLabel) {
        JLabel label = (JLabel)obj;
        DefaultTreeCellRenderer tempCellRenderer = new DefaultTreeCellRenderer();
        tempCellRenderer.setLeafIcon(label.getIcon());
        return  tempCellRenderer.getTreeCellRendererComponent(tree,label.getText(),
selected,expanded,true,row,hasFocus);
   }
   return super.getTreeCellRendererComponent(tree,value,
selected,expanded,leaf,row,hasFocus);
   }
}
目的只有一个,让实现了UI细节部分的DefaultTreeCellRenderer重用而已。这样,能实现都实现了,不能实现的也实现了,标签需要什么属性直接用tempCellRenderer的set方法即可!!虽然只有JLabel而已!呵呵。
至于如何操作控件我会放到JTable操作里面一起讲,因为他们都是实现了CellEditor接口,虽然一个是从TreeCellEditor派生,一个是从TableCellEditor派生!
分享到:
评论

相关推荐

    如何使用JTree,JTree使用方法

    ### 如何使用JTree:详解与实践 #### JTree简介 `JTree`是Java Swing中的一个组件,用于展示层次化的数据结构。它允许用户在应用程序中构建树形视图来表示目录结构、组织结构图等。`JTree`继承自`JComponent`类,...

    jtree

    在Java的Swing库中,`JTree`组件是一个用于展示层次数据的控件,它以树状结构显示数据。`jtree`标题所指的可能是关于如何在`JTree`中添加复选框(checkboxes)的功能。这通常是为了让用户能够多选树中的节点,进行...

    JTree的例子,可以拖动节点

    在Java Swing库中,`JTree`是一个非常重要的组件,用于显示和操作树形数据结构。这个例子展示了如何实现一个可拖动节点的`JTree`,这在用户界面设计中是一个常见且实用的功能,特别是在需要展示层次结构信息时。`...

    jTree和jTable 双向联动

    实现jTable和jTree的双向联动,点击jTree会选中jTable单元格,点击jTable会选中jTree节点。

    JAVA JTREE JTABLE实例代码

    在Java Swing库中,JTree和JTable是两个非常重要的组件,它们被广泛用于构建用户界面,特别是处理数据展示和交互。JTree用于显示层次结构的数据,而JTable则适用于二维表格形式的数据展现。 首先,我们来深入了解...

    Java JTree+JTable应用

    在Java Swing库中,`JTree`和`JTable`是两种非常重要的组件,用于创建用户界面。`JTree`通常用于展示层次化的数据结构,而`JTable`则适用于二维表格数据的显示和操作。本项目是关于如何在Java应用程序中结合使用这两...

    JTree的实现代码

    在IT领域,尤其是在Web开发中,`JTree`是一个常用组件,它用于在用户界面中展示数据的层次结构,比如文件系统、组织架构等。在本案例中,我们讨论的是一个使用JavaScript实现的JTree,这通常是通过HTML、CSS和...

    JTree

    **JTree 深度解析** `JTree` 是Java Swing库中的一个重要组件,它用于在用户界面中显示树状数据结构。这个组件允许用户以图形化的方式浏览和操作层次结构的数据,例如文件系统目录、数据库结构或者组织结构图。在...

    (一)如何使用JTree

    在Java Swing库中,JTree组件是一个非常有用的可视化控件,用于展示层次化的数据结构,如文件系统目录或组织结构图。这篇博文将探讨如何在Java应用程序中有效地使用JTree。 首先,理解JTree的基本概念至关重要。...

    java组件之jtree使用

    ### Java组件之JTree使用详解 #### 一、引言 `JTree`是Java Swing中的一个重要组件,用于展示层次化的数据结构。它提供了一种直观的方式来表示具有层级关系的数据,例如文件系统的目录结构或者组织架构等。本文将...

    JTree的Doc文档

    **JTree的Doc文档详解** Java Swing库中的`JTree`组件是用于显示和操作树状数据结构的可视化工具。这个组件允许用户以图形化的方式查看层次化的信息,如文件系统目录、数据库结构或者应用程序的对象模型。在Java...

    JTree用法大全 swing java

    ### JTree用法详解:Swing中的树状结构控件 在Java Swing中,`JTree`是一个非常重要的组件,用于展示层次结构的数据,如文件系统、组织结构图等。本文将详细介绍`JTree`的各种使用方法,包括如何创建、自定义外观、...

    Jtree

    在IT领域,JTree是一种广泛使用的Java Swing组件,它允许用户以树形结构来展示数据。这个组件在GUI(图形用户界面)应用中特别常见,因为它能清晰地组织层次化的信息,比如文件系统目录、数据库结构或者项目组织。...

    java使用jtree动态实现二叉树

    在Java编程中,`JTree`是Swing库中的一个组件,用于展示树形数据结构。这个组件在GUI(图形用户界面)应用中非常常见,因为它可以清晰地展示层次关系的数据,比如文件系统目录结构。在Java中动态实现二叉树,即在...

    JTree2.0 目录树

    **JTree 2.0:构建直观的目录树视图** `JTree`是Java Swing库中的一个组件,用于在用户界面中展示层次结构数据,通常表现为目录树的形式。在`JTree2.0`版本中,这个组件得到了进一步的改进和增强,提供更丰富的功能...

    java Swing JTree的教程实例

    在Java Swing中,JTree是一个非常重要的组件,用于展示层次结构的数据,通常以树状的形式显示。它在各种用户界面中都有广泛的应用,例如文件系统浏览、组织结构展示等。本教程将深入讲解如何使用JTree以及相关的操作...

    HTML转成Jtree

    而JTree则是一个Java库,它提供了一个可交互的树视图组件,常用于展示层次结构的数据。将HTML转换为JTree的过程主要是为了在Java应用程序中以树状结构展示HTML文档的结构。 要实现这个转换,我们需要以下步骤: 1....

    JTree的用法

    ### JTree的用法详解 #### 一、引言 `JTree` 是 Java Swing 库中的一个重要组件,用于在图形用户界面 (GUI) 中显示层次结构数据。它非常适合用来展示具有分层关系的信息,例如文件系统目录结构、组织结构等。 ####...

    jtree 节点添加图片

    在Java Swing库中,JTree是一个非常有用的组件,它用于展示层次结构的数据,例如文件系统或组织结构。在你的项目中,你似乎正在探索如何在JTree的不同节点上显示特定的图片,这可以增强用户的视觉体验,使得界面更加...

    JTree用法及JTree使用经验总结及源码

    JTree用法及JTree使用经验总结(吐血推荐) 1、初始化 2、三个经常使用的取值函数 3、根据node得到path:4、根据Path展开到该节点 5、根据path设定该节点选定 6、选中节点的方法 7、滚动到可见位置 8、给JTree添加右键...

Global site tag (gtag.js) - Google Analytics