以JPanel组件为画板,继承JPanel类并重写paint(Graphics g)函数,在函数中使用画笔g绘制树结构图。
实例代码——3个java源文件:Main.java、DrawNode.java、DrawTree.java
1、Main.java
package drawTree; public class Main { public static void main(String[] args){ DrawTree dt = new DrawTree(); DrawNode dn0 = new DrawNode("纹理",0,1024); DrawNode dn0_1 = new DrawNode(dn0,"密度","清晰"); DrawNode dn0_2 = new DrawNode(dn0,"触感","稍糊"); DrawNode dn0_3 = new DrawNode(dn0,"no","模糊"); DrawNode dn01_1 = new DrawNode(dn0_1,"no","0.4"); DrawNode dn01_2 = new DrawNode(dn0_1,"yes","0.6"); DrawNode dn01_3 = new DrawNode(dn0_1,"yes","0.8"); DrawNode dn02_1 = new DrawNode(dn0_2,"no","硬滑"); DrawNode dn02_2 = new DrawNode(dn0_2,"yes","软粘"); dt.function(dn0); } }
讯享网
2、DrawNode.java
讯享网package drawTree; public class DrawNode { String value = null; //当前节点的属性 DrawNode parentNode = null; //父结点 String lineValue = null; //与父结点连接的属性 int sonNodeNum = 0; //子结点个数 DrawNode[] sonNode = new DrawNode[10]; //子结点 int depth = 0; //深度 int beginX = 0; //以该节点为根节点的树前边界 int endX = 0; //以该节点为根节点的树后边界 boolean draw = false; //是否已经被绘制 int selfX = 0; //自身节点横坐标 int selfY = 0; //自身节点纵坐标 int parentX = 0; //父亲节点横坐标 int parentY = 0; //父亲节点纵坐标 DrawNode(String value,int beginX, int endX){ //根节点构造函数 this.value = value; this.beginX = beginX; this.endX = endX; this.depth = 0; this.selfX = beginX + (beginX+endX)/2; this.selfY = 0; } DrawNode(DrawNode parentNode, String value, String lineValue){ //不是根节点构造函数 this.parentNode = parentNode; this.value = value; this.lineValue = lineValue; this.parentX = parentNode.selfX; this.parentY = parentNode.selfY; this.depth = parentNode.depth+1; //自身x坐标是要根据父结点的子结点的个数动态改变 //this.selfX = parentNode.selfX+(-200+parentNode.sonNodeNum*200/(depth+1)); //这条语句可有可无,在树完全生成后,再确定每个节点的selfX this.selfY = parentNode.selfY+200; parentNode.sonNodeNum++; parentNode.sonNode[parentNode.sonNodeNum-1] = this; //setAllSonX(parentNode); } }
3、DrawTree.java
package drawTree; import java.awt.Graphics; import java.awt.image.BufferedImage; import javax.swing.*; public class DrawTree { int WIDTH = 1024; int HEIGHT = 1024; DrawNode root = null; void function(DrawNode dn){ JFrame jf = new JFrame(); jf.setTitle("树"); jf.setSize(WIDTH, HEIGHT); MyPanel mp = new MyPanel(); setX(dn); mp.root = dn; jf.add(mp); jf.setVisible(true); } //递归函数,设置树中每个节点的selfX void setX(DrawNode root){ //设置子结点的beginX和endX int gap = (root.endX-root.beginX)/(root.sonNodeNum+1); for(int i=0;i<root.sonNodeNum;i++){ root.selfX = root.beginX+(root.endX-root.beginX)/2; root.sonNode[i].selfX = root.beginX+(i+1)*gap; root.sonNode[i].beginX = root.sonNode[i].selfX-gap/2; root.sonNode[i].endX = root.sonNode[i].selfX + gap/2; root.sonNode[i].parentX = root.selfX; if(root.sonNode[i]!= null){ setX(root.sonNode[i]); } } } } class MyPanel extends JPanel{ DrawNode root = null; private static final long serialVersionUID = 1L; public void paint(Graphics g){ //调用paint获得组件JPanel的画笔,以组件为画板 DrawNode tmp = root; int x = 0; int num = 0; if(tmp != null){ num = 1; } //类似非递归函数遍历树的节点 while(x<num){ // int depth = tmp.depth; if(tmp.draw == false){ if(tmp.sonNodeNum==0){ }else{ num = num + tmp.sonNodeNum; } g.drawOval(tmp.selfX, tmp.selfY, 50, 50); g.drawString(tmp.value, tmp.selfX+25, tmp.selfY+25); if(tmp != root){ g.drawLine(tmp.selfX+25, tmp.selfY+25, tmp.parentX+25, tmp.parentY+25); g.drawString(tmp.lineValue, (tmp.selfX+tmp.parentX+50)/2, (tmp.selfY+tmp.parentY+50)/2); } tmp.draw = true; x++; }else{ int y = -1; for(int i=0;i<tmp.sonNodeNum;i++){ if(tmp.sonNode[i].draw == false){ y=i; break; } } if(y!=-1){ //还有子结点为绘画。 tmp = tmp.sonNode[y]; continue; //进入子结点,重新循环 }else{ //之下的全部结点都以绘完 if(tmp ==root){ break; //为根节点就退出 }else{ tmp = tmp.parentNode; continue; } } } if(tmp.sonNodeNum == 0){ //叶子节点,回到父结点 tmp = tmp.parentNode; }else{ //不是叶子节点,进入下一层 tmp = tmp.sonNode[0]; } } } }
运行结果:
新人,代码不好,多多包含。。。
之后可能会尽可能地完善一下。。

补充01:
代码运行方式:
1、放在eclipse项目的同一个包下,且三个java文件中的package要一致,即可直接运行。
2、控制台运行步骤:






版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/122563.html