Java学习笔记(八)

画板重绘+抽象画绘制

一、重绘:

可能你注意到了,之前在写画板的时候,当你改变画板的大小或者最小化之类的操作,你画的图像消失了。有想过为什么会消失吗?之前说过,我们所看到的东西都是画出的。当画板大小改变后,原来的图形界面并不能满足显示要求了,需要读取新的数据,而这个数据并没有被保存下来。通俗的讲:就算你之前画出来的图形没有保存,所以当画板大小改变的时候,并没有数据给它重绘。

所以我们现在要做的事就是将画出来的图形保存,然后在重绘出来。想一下,一个图形有多少个属性呢?颜色、粗细、图形种类......如此之多如何保存呢?肯定不能一个一个保存,这样代码量很大。咱们画的图形其实就算一个对象,那么我直接保存这个对象就可以保存它携带的信息了。所以可以使用数组或者队列进行保存。我选择数组,缺点就是要给定大小,而队列却不用。

定义保存的数组: private Shape[] array = new Shape[1000];(表示最多保存一千个图形)

既然要重绘,那么需要写一个重绘的类,重绘的时候调用它的方法进行重绘。一句话,就算将你原来画板制图的方法写到一个新的类里面,原来的类负责将制图的数据保存下来并传给新的类并调用新类的方法。比如我原来画图的是DrawListener类,我新写了一个Shape类,Shape类中有一个画图的方法Draw(),在DrawListener中,Shape的类负责保存数据同时制图(这个时候并不是重绘,就相当于现在的Shape替代了原来的DrawListener,重绘只有当窗体大小被改变的时候自动触发)。最关键的地方就是重新JFrame中绘图的方法paint,这个方法是自动触发的(窗体大小改变的时候)。重写内容就是让它绘制之前保存下来的图形,这个时候叫重绘。

代码如下:

public void paint(Graphics G)
{
super.paint(G);//调用父类的制图方法
for(int i=0;i<array.length;i++)
{
Shape s = array[i];
if(s!=null)
{
s.Draw(G);//绘图
}
}

}

保存图形的方法,比如画直线的时候:

if(shape.equals("直线"))
    {
    //G.setStroke(new BasicStroke(2));
    //G.drawLine(x1, y1, x2, y2);
    Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(1), "直线");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
   

    }

其中Shape的构造方法可根据你需要传的参数进行重载即可。

二、抽象化的绘制:

其实就是根据某个函数绘制很多个点,这里我贴个网址,提供了很多抽象化的函数和初始化参数:http://paulbourke.net/fractals/。然后套个循环限制一下画的点数就好。

贴下完整代码:

//Shape:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
public class Shape {
public int x1,x2,y1,y2;
public Color color;
public Stroke  stroke;
public String type;
private Graphics2D G;
private int ex,ey,sy,sx;
private int flag=1;
private int count=0;

public Shape(int x1, int y1, int x2, int y2, Color color, Stroke stroke,
String type) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.stroke = stroke;
this.type = type;
}
public Shape(int x1, int y1, int x2, int y2,int ex,int ey,int sx,int sy,int flag, Color color, Stroke stroke,
String type) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.ex = ex;
this.ey = ey;
this.sx = sx;
this.sy = sy;
this.color = color;
this.stroke = stroke;
this.type = type;
this.flag = flag;
}
public Shape(int x1, int y1, int x2, int y2,int ex,int ey,int sx,int sy,int flag,int count, Color color, Stroke stroke,
String type) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.ex = ex;
this.ey = ey;
this.sx = sx;
this.sy = sy;
this.color = color;
this.stroke = stroke;
this.type = type;
this.flag = flag;
this.count=count;
}

public void drawduobian(int x1,int y1,int x2,int y2)
{


/* G.drawLine(x1, y1, x2, y2);
if(Math.abs(x2-temp1)<10|| Math.abs(y2-temp2)<10)
    {
    G.drawLine(temp1, temp2, x2, y2);
    count=0;
    }*/
// G.setStroke(new BasicStroke(2));


}
public void Draw(Graphics gr )
{
Graphics2D g = (Graphics2D) gr;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(stroke);
g.setColor(color);
if (type.equals("直线")) {
g.drawLine(x1, y1, x2, y2);
}
else if(type.equals("等腰三角形"))
{
if(y1-y2!=0 && x1-x2!=0)
{
int T = (y1-y2)/(x1-x2);
int a = (int) Math.atan(T);
int L = (int) Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
int x3 = (int) (x2+(int)L*Math.cos(a+60));
int y3 = (int) (y2+(int)L*Math.sin(a+60));
int[]x={x1,x2,x3};
int[]y={y1,y2,y3}; 
g.drawPolygon(x, y, 3);
}
}
else if(type.equals("圆"))
{
g.drawOval(x1, y1, x2, y2);
}
else if(type.equals("橡皮"))
{
g.drawLine(x1, y1, x2, y2);
}
else if(type.equals("刷子"))
{
g.drawLine(x1, y1, x2, y2);
}
else if(type.equals("喷枪"))
{
g.drawLine(x1, y1, x1, y1);
g.drawLine(x1+x2, y1+y2, x1+x2, y1+y2);
}
else if(type.equals("虚线"))
{
Graphics2D g2d = (Graphics2D) g;
        //float dash[] = {10.0f};
        Stroke dashed = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0);
        g2d.setStroke(dashed);//线的宽度、线的样式、拐角的样式、限制尖角、线长和缺口长度、开始画的偏移量
        g2d.drawLine(x1, y1, x2, y2);
}
else if(type.equals("曲线"))
{
g.drawLine(x1, y1, x2, y2);
}
else if(type.equals("任意多边形"))
{
g.setStroke(new BasicStroke(2));
if(flag==1)
{
g.drawLine(x1, y1, x2, y2);


}
else if(flag==2)
{
g.drawLine(ex, ey, x2, y2);
if (count == 2
|| (Math.abs(x2 - sx) < 15 && Math.abs(y2 - sy) < 15)) {
g.drawLine(sx, sy, x2, y2);
flag = 1;
}

}
}
}

}

//DrawJFrame

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;


import javax.swing.JButton;
import javax.swing.JFrame;
public class DrawJFrame extends JFrame{
public static void main(String []args)
{
DrawJFrame J = new DrawJFrame();
J.initUI();
}
private Shape[] array = new Shape[1000];
public void initUI()
{
this.setTitle("画板");
this.setSize(700, 500);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setLayout(new FlowLayout());

Graphics g = this.getGraphics();


DrawListener Dr = new DrawListener(g,array);



String[] shape ={"直线","圆","等腰三角形","任意多边形","刷子","喷枪","橡皮","曲线","虚线","抽象画"};
for(int i=0;i<shape.length;i++)
{
JButton button = new JButton(shape[i]);
button.setPreferredSize(new Dimension(100,20));
button.addActionListener(Dr);
this.add(button);
}
Color[] color={Color.red,Color.BLACK,Color.green};
for(int i=0;i<color.length;i++)
{
JButton button = new JButton();
button.setBackground(color[i]);
button.setPreferredSize(new Dimension(50,50));
button.addActionListener(Dr);
this.add(button);
}
this.setVisible(true);

Dr.setG(getGraphics());
Dr.setF(this);//重点
this.addMouseListener(Dr);
this.addMouseMotionListener(Dr);
}

public void paint(Graphics G)
{
super.paint(G);
for(int i=0;i<array.length;i++)
{
Shape s = array[i];
if(s!=null)
{
s.Draw(G);
}
}
}

}

//DrawListener

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;


import javax.swing.JButton;
import javax.swing.JFrame;


import java.awt.Image;
import java.lang.Math;
import java.util.Random;
public class DrawListener extends MouseAdapter implements ActionListener {

   private int x1,x2,y1,y2;
   private Graphics2D G;
   private Graphics g;
   private int sx,sy,ex,ey;
   private int flag = 1;
   private Color color = Color.BLACK;
   private String shape="直线";
   private JFrame frame;
   private Shape[] array;//保存绘制图形的对象数组
   private int index;//数组下标
   
   public DrawListener(Graphics g, Shape[] array) {
this.g = g;
this.array = array;
}
  
   
   public void setF(JFrame J)
  {
  frame =J;
  }
   

public void setG(Graphics g)
{
G = (Graphics2D)g;
this.G.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
 
  public void actionPerformed(ActionEvent e)
  {
  if(e.getActionCommand().equals(""))//表示点击的当时选择颜色的按钮
  {
  JButton button = (JButton)e.getSource();
  color = button.getBackground();//获取按钮的颜色

  }
  else//点击的是有文字的按钮
  {
  shape = e.getActionCommand();
  }
  }
 
 
/* public void drawTrangle(int x1,int y1,int x2,int y2)
{
if(y1-y2!=0 && x1-x2!=0)
{
int T = (y1-y2)/(x1-x2);
int a = (int) Math.atan(T);
int L = (int) Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
int x3 = (int) (x2+(int)L*Math.cos(a+60));
int y3 = (int) (y2+(int)L*Math.sin(a+60));
int[]x={x1,x2,x3};
int[]y={y1,y2,y3}; 
G.drawPolygon(x, y, 3);
}

}*/
int count = 0;
int temp1 = 0;
int temp2 = 0;
int tempx2 = 0;
int tempy2 = 0;
int close = 0;
public void drawduobian(int x1,int y1,int x2,int y2)
{


/* G.drawLine(x1, y1, x2, y2);
if(Math.abs(x2-temp1)<10|| Math.abs(y2-temp2)<10)
    {
    G.drawLine(temp1, temp2, x2, y2);
    count=0;
    }*/
G.setStroke(new BasicStroke(2));
G.drawLine(x1, y1, x2, y2);
sx = x1;
sy = y1;
ex = x2;
ey = y2;
flag++;


}

public void mouseClicked(MouseEvent e){
if (shape.equals("任意多边形") && flag == 2) {
x2 = e.getX();
y2 = e.getY();
int count = e.getClickCount();
//G.drawLine(ex, ey, x2, y2);
Shape s = new Shape(x1, y1, x2, y2,ex,ey,sx,sy,flag, color, new BasicStroke(1), "任意多边形");
s.Draw(G);
if(index<1000)
{
array[index++]=s;
}
if (count== 2
|| (Math.abs(x2 - sx) < 15 && Math.abs(y2 - sy) < 15)) {
Shape sw = new Shape(x1, y1, x2, y2,ex,ey,sx,sy,flag,count, color, new BasicStroke(1), "任意多边形");
sw.Draw(G);
if(index<1000)
{
array[index++]=s;
}
//G.drawLine(sx, sy, x2, y2);
flag = 1;
}

ex = x2;
ey = y2;

}

}


    /**
     * Invoked when a mouse button has been pressed on a component.
     */

    public void mousePressed(MouseEvent e){
   
    System.out.println("鼠标被按下!");
    G.setColor(color);
    x1 = e.getX();
    y1 = e.getY();
    if(count==0)
    {
    temp1 = x1;
    temp2 = y1;
    }
    count++;
   
   


    }
    public void drawDashedLine(int x1, int y1, int x2, int y2){
        Graphics2D g2d = (Graphics2D) G;
        //float dash[] = {10.0f};
        Stroke dashed = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0);
        g2d.setStroke(dashed);//线的宽度、线的样式、拐角的样式、限制尖角、线长和缺口长度、开始画的偏移量
        g2d.drawLine(x1, y1, x2, y2);
    }


    /**
     * Invoked when a mouse button has been released on a component.
     */
    public void mouseReleased(MouseEvent e){
    System.out.println("鼠标被释放!");
    x2 = e.getX();
    y2 = e.getY();
    tempx2 = x2;
    tempy2 = y2;
    if(shape.equals("直线"))
    {
    //G.setStroke(new BasicStroke(2));
    //G.drawLine(x1, y1, x2, y2);
    Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(1), "直线");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
   
    }
    else if(shape.equals("等腰三角形"))
    {
    //G.setStroke(new BasicStroke(2));
    //this.drawTrangle( x1, y1, x2, y2);
    Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(1), "等腰三角形");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
    }


    else if (shape.equals("任意多边形") && flag == 1) {
    //this.drawduobian( x1, y1, x2, y2);
        //G.setStroke(new BasicStroke(2));
//G.drawLine(x1, y1, x2, y2);
    Shape s = new Shape(x1, y1, x2, y2,ex,ey,sx,sy,flag, color, new BasicStroke(1), "任意多边形");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
    sx = x1;
sy = y1;
ex = x2;
ey = y2;
flag++;
   
   
}
    else if(shape.equals("圆"))
    {
    //G.setStroke(new BasicStroke(2));
    //G.drawOval(Math.min(x1,x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
    Shape s = new Shape(Math.min(x1,x2), Math.min(y1, y2),Math.abs(x1-x2), Math.abs(y1-y2), color, new BasicStroke(1), "圆");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
    }
    else if(shape.equals("橡皮"))
    {
    color = frame.getContentPane().getBackground();
    G.setColor(color);
    x2 = e.getX();
y2 = e.getY();
//G.setStroke(new BasicStroke(100));
//G.drawLine(x1, y1, x2, y2);
Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(100), "橡皮");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }

    }
    else if(shape.equals("刷子"))
    {
    //G.setStroke(new BasicStroke(20));
//G.drawLine(x1, y1, x2, y2);
Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(20), "刷子");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
    }
    else if(shape.equals("喷枪"))
    {
    Random random = new Random();
    // G.drawLine(x2, y2, x2, y2);   
             for (int i = 0; i < 10; i++) {  
                 int p = random.nextInt(10);  
                 int q = random.nextInt(10);  
                 //G.drawLine(x2 + p, y2 + q, x2 + p, y2 + q);  
                Shape s = new Shape(x2, y2, p, q, color, new BasicStroke(2), "喷枪");
    s.Draw(G);
    if(index<1000)
    {
    array[index++]=s;
    }
    }
    }
    else if(shape.equals("虚线"))
    {
    //drawDashedLine(x1,y1, x2,  y2);
    Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(2), "虚线");
      s.Draw(G);
      if(index<1000)
      {
      array[index++]=s;
      }
   
    }
    else if(shape.equals("抽象画"))
    {
    double x=0,y=0;
    double a=2,b=-30,c=-1.9,d=1.9;
    for(int i=0;i<100000;i++)
    {
    x = y-Math.signum(x)*Math.sqrt(Math.abs(b*x-c));
    y = a-x;
    int m=(int)((d*Math.sin(a*x)-Math.sin(b*y))*100+930);
   
    int n=(int)((c*Math.cos(a*x)-Math.cos(b*y))*100+550);
    G.setColor(new Color(250,i%255,i%155));
    G.drawLine(m, n, m, n);
   
    }
    }
    //G.drawLine(x1, y1, x2, y2);
    //G.drawOval(x2, y2, 100, 100);//画圆的
    //G.drawRect(x1, y1, 200, 100);//画矩形的
    //G.drawString("AAA", x1, y1);//画文字的
    //javax.swing.ImageIcon IMG = new javax.swing.ImageIcon("C:\\Users\\25280\\Desktop\\综合文件夹\\收稿\\摄影作品_张雨泉\\5.jpg");
    //Image img = IMG.getImage();
    //G.drawImage(img, x1, y1,null);
    //G.fill3DRect(x1, y1, 100, 100, true);
    //G.fillOval(x1, y1, 100, 100);
    //G.fillRoundRect(x1, y1, 100, 100, 50, 50);
    //this.drawTrangle(x1, y1, x2, y2);
    //this.drawduobian(x1, y1, x2, y2);
      
    }
    private int nextInt(int i) {
// TODO Auto-generated method stub
return 0;
}




public void mouseDragged(MouseEvent e) {
if (shape.equals("曲线")) {
x2 = e.getX();
y2 = e.getY();
//G.setStroke(new BasicStroke(10));
//G.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
Shape s = new Shape(x1, y1, x2, y2, color, new BasicStroke(2), "曲线");
      s.Draw(G);
      if(index<1000)
      {
      array[index++]=s;
      }
   

}

}


    /**
     * Invoked when the mouse enters a component.
     */
    public void mouseEntered(MouseEvent e){
    System.out.println("鼠标进入画板!");
   
    }


    /**
     * Invoked when the mouse exits a component.
     */
    public void mouseExited(MouseEvent e){
    System.out.println("鼠标离开画板!");
   
    }
    

}

运行效果图:

(1)重绘:

未改变窗体大小:

Java学习笔记(八)

改变窗体大小:

Java学习笔记(八)

这样实现重绘了。

(2)抽象话:

我用的函数和参数如下:

Java学习笔记(八)

效果图:

Java学习笔记(八)

好丑啊!23333

有不懂的地方欢迎给我留言!