图形的实现
利用面向对象的方法,将图形抽象为一个一个对象,可以实现图形的重现
package DrawingBoaard.v2;
import java.awt.*;
import java.util.Random;
public class Shape
{
String str;
int x1,y1,x2,y2;
Color color;
int count = 0;
Shape(String str,int x1,int y1,int x2,int y2,Color color)
{
this.str = str;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
}
public void draw(Graphics g)
{
g.setColor(color);
switch (str)
{
case "直线":
g.drawLine(x1, y1, x2, y2);
break;
case "矩形":
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
break;
case "实心矩形":
g.fillRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
break;
case "圆形":
g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
break;
case "实心圆形":
g.fillOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
break;
case "等腰三角形":
g.drawLine(x1,y1,x2,y2);
g.drawLine(x2,y1,(x1+x2)/2,y2);
g.drawLine((x1+x2)/2,y2,x1,y1);
break;
case "立方体":
cube(g,x1,y1,x2,y2);
break;
case "谢尔宾斯基三角形":
double[] third = thirdVertexUnder(x1,y1,x2,y2);
triangle(g,x1,y1,x2,y2,(int)third[0],(int)third[1]);
SierpinskiTriangle( g, x1, y1, x2, y2);
break;
case "曲线":
curve(g,x1,y1,x2,y2,500);
}
}
public double distance(double x1, double y1, double x2, double y2)
{
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}//计算两边长度
public double[] MidpointCoordinates(double x1, double y1, double x2, double y2)
{
double midX = (x1 + x2) / 2;
double mixY = (y1 + y2) / 2;
return new double[]{midX,mixY};
}//计算中点坐标
public double[] thirdVertexUnder(double x1, double y1, double x2, double y2)
{
double midX = (x1 + x2) / 2;
double midY = (y1 + y2) / 2;
double baseLength = distance(x1, y1, x2, y2);
double height = baseLength * Math.sqrt(3) / 2;
double thirdX = midX;
double thirdY = midY - height;
return new double[]{thirdX, thirdY};
}//计算三角形顶点坐标(under)
public double[] thirdVertexUp(double x1, double y1, double x2, double y2)
{
double midX = (x1 + x2) / 2;
double midY = (y1 + y2) / 2;
double baseLength = distance(x1, y1, x2, y2);
double height = baseLength * Math.sqrt(3) / 2;
double thirdX = midX;
double thirdY = midY + height;
return new double[]{thirdX, thirdY};
}//计算三角形顶点坐标(up)
public void triangle(Graphics g ,int x1,int y1,int x2,int y2,int x3,int y3 )
{
g.drawLine(x1,y1,x2,y2);
g.drawLine(x2,y2,x3,y3);
g.drawLine(x3,y3,x1,y1);
}
public void filltriangle(Graphics g, double x1, double y1, double x2, double y2, double x3, double y3)
{
int[] xp = {(int)x1, (int)x2, (int)x3};
int[] yp = {(int)y1, (int)y2, (int)y3};
g.fillPolygon(xp,yp,3);
}
public void cube(Graphics g,int x1,int y1,int x2,int y2)
{
double l = distance(x1,y1,x2,y2);
g.drawLine(x1,y1,x2,y2);
g.drawLine(x2,y2, (int) (x2+0.5*l), (int) (y2+0.5*l));
g.drawLine((int) (x2+0.5*l), (int) (y2+0.5*l),(int) (x1+0.5*l), (int) (y1+0.5*l));
g.drawLine((int) (x1+0.5*l), (int) (y1+0.5*l),x1,y1);
g.drawLine(x1,(int)(y1+l),x2,(int) (y2+l));
g.drawLine(x2,(int) (y2+l),(int) (x2+0.5*l), (int) (y2+1.5*l));
g.drawLine((int) (x2+0.5*l), (int) (y2+1.5*l),(int) (x1+0.5*l), (int) (y1+1.5*l));
g.drawLine((int) (x1+0.5*l), (int) (y1+1.5*l),x1,(int)(y1+l));
g.drawLine(x1,y1,x1,(int)(y1+l));
g.drawLine(x2,y2,x2,(int)(y2+l));
g.drawLine((int) (x2+0.5*l), (int) (y2+0.5*l),(int) (x2+0.5*l), (int) (y2+1.5*l));
g.drawLine((int) (x1+0.5*l), (int) (y1+0.5*l),(int) (x1+0.5*l), (int) (y1+1.5*l));
}//立方体
public void SierpinskiTriangle(Graphics g,int x1, int y1, int x2, int y2)
{
if(distance(x1,y2,x2,y2)<10)
{
return;
}
double[] third = thirdVertexUnder(x1,y1,x2,y2);
double[] mid1 = MidpointCoordinates(x1,y1,x2,y2);
double[] mid2 = MidpointCoordinates(x2,y2,third[0],third[1]);
double[] mid3 = MidpointCoordinates(third[0],third[1],x1,y1);
filltriangle(g,mid1[0],mid1[1],mid2[0],mid2[1],mid3[0],mid3[1]);
SierpinskiTriangle(g,x1,y1,(int)mid1[0],(int)mid1[1]);
SierpinskiTriangle(g,x2,y2,(int)mid1[0],(int)mid1[1]);
SierpinskiTriangle(g,(int)mid2[0],(int)mid2[1],(int)mid3[0],(int)mid3[1]);
}
public void curve(Graphics g,int x1,int y1,int x2,int y2,int n)
{
Random random = new Random();
int rand = random.nextInt(n)-n/2;
if(n<=5)
{
g.drawLine(x1,y1,x2,y2);
return;
}
curve(g,x1,y1,(x1+x2)/2,(y1+y2)/2+rand,n/2);
curve( g,(x1+x2)/2,(y1+y2)/2+rand,x2,y2,n/2);
//curve(g,(x1+x2)/2,(y1+y2)/2,x2,y2,n/2);
}
}
其中"谢尔宾斯基三角形","曲线"用到了递归的方法,具体的递归原理可以看这个视频。
重载JFrame
原本的JFrame中的“paint”会刷新之前画过的图形,改变“paint”方法,之重绘之前的图形,这里用到了之前提到的面向对象的方法
package DrawingBoaard.v2;
import javax.swing.*;
import java.awt.*;
public class MyJFrame extends JFrame
{
public Shape[] shapeList = null;
public void paint(Graphics g)
{
super.paint(g);
for(int i = 0;i<shapeList.length;i++)
{
Shape shape = shapeList[i];
if(shape !=null)
{
shape.draw(g);
}
}
}
}
监听器以及方法
主要是接受来自鼠标和按钮信息,然后传递给图形方法
package DrawingBoaard.v2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class DrawFun implements MouseListener, ActionListener
{
public Graphics g = null;
int x1 = 0,y1 = 0,x2 = 0,y2 = 0,x3=0,y3=0;
int x11,y11,x22,y22,x33,y33;
int count = 0;
String type = " ";
Shape[] myshape = new Shape[100];
int i = 0 ;
Color color1 = null;
public void setG(Graphics g )
{
this.g = g;
}
public int abs(int a )
{
return a < 0 ? -a : a;
}
@Override
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals(" "))
{
JButton btn = (JButton) e.getSource();
color1 = btn.getBackground();
g.setColor(color1);
}
else
{
type = e.getActionCommand();
}
}
@Override
public void mouseClicked(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
if(type.equals("三角形"))
{
if (count == 0)
{
x11 = x;
y11 = y;
count++;
}
else if (count == 1)
{
x22 = x;
y22 = y;
Shape shape = new Shape("直线",x11,y11,x22,y22,color1);
shape.draw(g);
myshape[i++] = shape;
count++;
}
else if(count==2)
{
x33 = x;
y33 = y;
Shape shape = new Shape("直线",x22,y22,x33,y33,color1);
shape.draw(g);
myshape[i++] = shape;
Shape shape1 = new Shape("直线",x11,y11,x33,y33,color1);
shape1.draw(g);
myshape[i++] = shape1;
count = 0;
}
}
else if(type.equals("多边形"))
{
if(count == 0 )
{
x11 = x;
y11 = y;
count++;
}
else if(count == 1 )
{
x22 = x;
y22 = y;
Shape shape = new Shape("直线",x11,y11,x22,y22,color1);
shape.draw(g);
myshape[i++] = shape;
count++;
}
else if(count == 2)
{
x33 = x;
y33 = y;
Shape shape1 = new Shape("直线",x22,y22,x33,y33,color1);
shape1.draw(g);
myshape[i++] = shape1;
x22 = x33;
y22 = y33;
if(Math.abs(x11-x33)<10 && Math.abs(y11-y33)<10)
{
Shape shape3 = new Shape("直线",x11,y11,x33,y33,color1);
shape3.draw(g);
myshape[i++] = shape3;
count=0;
}
}
}
}
@Override
public void mousePressed(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
x1 = x;
y1 = y;
}
@Override
public void mouseReleased(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
x2 = x;
y2 = y;
Shape shape = new Shape(type,x1,y1,x2,y2,color1);
shape.draw(g);
myshape[i++] = shape;
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
}
主函数
package DrawingBoaard.v2;
import javax.swing.*;
import java.awt.*;
public class DrawingShow
{
public void show()
{
DrawFun dl = new DrawFun();
MyJFrame draw = new MyJFrame();
draw.setTitle("画板");
draw.setSize(800,500);
draw.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw.setLocationRelativeTo(null);
draw.setLayout(new FlowLayout());
draw.addMouseListener(dl);
String[] btnTexts = {"直线", "矩形", "圆形", "实心矩形", "实心圆形", "等腰三角形", "三角形", "多边形","谢尔宾斯基三角形", "曲线","立方体", "球", "橡皮擦", "撤回", "保存"};
for (String btnText : btnTexts)
{
JButton btn = new JButton(btnText);
draw.add(btn);
btn.addActionListener(dl);
}//将这些按钮添加到draw容器中,同时为每个按钮添加一个动作监听器
Color[] colors = {Color.BLACK, Color.WHITE, Color.GRAY, Color.LIGHT_GRAY, Color.DARK_GRAY, Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.ORANGE, Color.PINK,};
for(Color color : colors)
{
JButton btn = new JButton(" ");
btn.setBackground(color);
draw.add(btn);
btn.addActionListener(dl);
}//将这些按钮添加到draw容器中,同时为每个按钮添加一个动作监听器
draw.setVisible(true);
Graphics g = draw.getGraphics();
dl.setG(g);
draw.shapeList = dl.myshape;
}
public static void main(String[] args)
{
DrawingShow test = new DrawingShow();
test.show();
}
}
MyJFrame创建窗体
创建Graphics要在“可视化之后”,否则会出现g为空的现象
要将监听器的图形对象地址传递给MyJFrame,当窗体发生刷新是,以实现图形的重绘