Java實驗8 T6.繪製一個二叉樹
阿新 • • 發佈:2020-12-30
技術標籤:Java
繪製如下形式的一個二叉樹
package text8;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
public class Drawing {
// 以下是常量
private static final String PATH = "tree.png";
// 畫板長度
private static final int WIDTH = 800;
// 畫板寬度
private static final int HEIGHT = 500;
// 圓形半徑
private static final int OVAL_RADIUS = 15;
// 字型大小
private static final int FONT_SIZE = 15;
// 根據字型位數,選擇字型偏移量
private static final int offset_1 = 12;
private static final int offset_2 = 9;
private static final int offset_3 = 4;
//畫連線時的偏移量
private static final int LINE_OFFSET = 3;
//字型格式
private static final String FONT_STYLE = "宋體";
//圖片格式
private static final String IMAGE_STYLE = "PNG";
//寫數字時用到的偏移量
private static final int FONT_OFFSET = 1;
//父圓形與子圓形之間的偏移量
private static final int OVAL_OFFSET = 10;
//root結點的y座標
private static final int ROOT_Y = 50;
//圖形快取區
private BufferedImage bi;
//畫圖筆
private Graphics2D g2;
//以下是變數
// 當前圓位置和值
private int my_x;
private int my_y;
private char val;
// 當前字型位置
private int my_font_x;
private int my_font_y;
private void initSettings(){
//得到圖片緩衝區
bi = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
//得到繪製環境(這張圖片的筆)
g2 = (Graphics2D) bi.getGraphics();
g2.fillRect(0,0,WIDTH,HEIGHT);
g2.setBackground(Color.WHITE);
g2.setColor(Color.BLACK);
g2.setFont(new Font(FONT_STYLE,Font.PLAIN,FONT_SIZE));
}
private void closeSettings() throws IOException {
ImageIO.write(bi,IMAGE_STYLE,new FileOutputStream(PATH));
}
public static class DrawNode{
protected char val;
protected DrawNode left;
protected DrawNode right;
public DrawNode() {}
public DrawNode(char val) {
this.val = val;
}
public DrawNode(char val, DrawNode left, DrawNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
/**
* 畫一個圓,包括數字
*/
private void drawOval(){
g2.drawOval(my_x,my_y,OVAL_RADIUS*2,OVAL_RADIUS*2);
my_font_y = my_y+OVAL_RADIUS+FONT_SIZE/2-FONT_OFFSET;
switch (String.valueOf(val).length()){
case 1: my_font_x = my_x+offset_1;break;
case 2: my_font_x = my_x+offset_2;break;
case 3: my_font_x = my_x+offset_3;break;
default: System.out.println("值為"+String.valueOf(val).length()+"位數,不支援!");
}
g2.drawString(String.valueOf(val),my_font_x,my_font_y);
}
/**
* 畫連線
* @param isLeft 父結點與子結點的關係
* @param parent_x 父結點的x座標
* @param parent_y 父結點的y座標
*/
private void drawLine(boolean isLeft,int parent_x,int parent_y){
int parent_point_x;
int parent_point_y;
int my_point_x;
int my_point_y;
if(isLeft){
parent_point_x = parent_x+OVAL_RADIUS/2-LINE_OFFSET;
parent_point_y = parent_y+(3*OVAL_RADIUS)/2+LINE_OFFSET;
my_point_x = my_x+(3*OVAL_RADIUS)/2+LINE_OFFSET;
my_point_y = my_y+OVAL_RADIUS/2-LINE_OFFSET;
}else{
parent_point_x = parent_x+(3*OVAL_RADIUS)/2+LINE_OFFSET;
parent_point_y = parent_y+(3*OVAL_RADIUS)/2+LINE_OFFSET;
my_point_x = my_x+OVAL_RADIUS/2-LINE_OFFSET;
my_point_y = my_y+OVAL_RADIUS/2-LINE_OFFSET;
}
g2.drawLine(parent_point_x,parent_point_y,my_point_x,my_point_y);
}
/**
* 一邊中序遍歷一邊畫圖
* @param node
*/
private void firstTraverseAndDraw(DrawNode parentNode,DrawNode node,boolean isLeft,int parent_x,int parent_y){
if(node == null){
return;
}
//只畫當前結點,而不畫父結點。但是要根據父結點與當前結點的關係,確定當前結點的位置,並將連線畫出來
val = node.val;
if(parentNode == null){
my_x = WIDTH/2 - OVAL_RADIUS;
my_y = ROOT_Y;
}else{
my_y = parent_y+2*OVAL_RADIUS+OVAL_OFFSET;
if(isLeft){
my_x = parent_x-2*OVAL_RADIUS-OVAL_OFFSET;
}else{
my_x = parent_x+2*OVAL_RADIUS+OVAL_OFFSET;
}
drawLine(isLeft,parent_x,parent_y);
}
drawOval();
// 遞迴畫出左子樹和右子樹
parent_x = my_x;
parent_y = my_y;
firstTraverseAndDraw(node,node.left,true,parent_x,parent_y);
firstTraverseAndDraw(node,node.right,false,parent_x,parent_y);
}
public DrawNode build(){
// 此處輸入樹上的點
return a;
}
public void drawEntrance(DrawNode drawNode) throws IOException {
initSettings();
firstTraverseAndDraw(null,drawNode,true,0,0);
closeSettings();
}
public static void main(String[] args) throws IOException {
Drawing d = new Drawing();
//先構建一顆二叉樹
DrawNode root = d.build();
//呼叫入口方法畫圖
d.drawEntrance(root);
}
}