[size=medium]在以前制作的简单画板中,每当变动窗体时画出的图形都会消失,这个问题就需要通过重绘来实现。
重绘的原理:屏幕上的所有东西事实上都是由一个个的点绘制而成,包括窗体本身。JFrame类中有一个方法paint(),每当打开窗体时系统都会自动调用这个方法,把窗体画出来。
那么要想在窗体变动时窗体上画出的图案和窗体一样仍然存在,可以在定义时重写paint()的方法,在其中写上画这些图形的方法。这样,就需要从事件处理类中获得一些坐标,由于坐标的数量不定,而且画的基本图形不定,可以用队列存储这些信息。队列中的每个元素是一个数组,用数组中的第一个元素存储画的基本图形。
1、在事件处理类中,定义一个队列作为属性,存储坐标
2、在写绘制方法时,每次画基本图形时都新建一个数组存储坐标,把数组加入队列,同时用数组中指定的元素表示基本图形的种类(比如下面的例子中我用每个数组的第一个元素表示图形的种类)
3、在paint()方法中调用事件处理类中队列的数据,根据表示图形种类的元素的值绘制图形
如下是重绘谢尔宾斯基地毯的部分代码:[/size]
1、在事件处理类中,定义一个队列作为属性,存储坐标
static SingleLinkList mylinklist = new SingleLinkList();
2、在写绘制方法时,每次画基本图形时都新建一个数组存储坐标,把数组加入队列,同时用数组中指定的元素表示基本图形的种类
/**
* 用square1绘制最大的正方形(边框为黑色)
* @param x1
* @param x2
* @param a
* @param count
*/
public void square1(int x1,int x2,int a,int count){
//绘制最大的正方形
g.setColor(Color.BLACK);
g.drawRect(x1, x2, a, a);
int[] shape1=new int[5];
shape1[0]=21;shape1[1]=x1;shape1[2]=x2;shape1[3]=a;shape1[4]=a;
mylinklist.add(shape1);
g.drawRect(x1-1, x2-1, a+2, a+2);
int[] shape2=new int[5];
shape2[0]=21;shape2[1]=x1-1;shape2[2]=x2-1;shape2[3]=a+2;shape2[4]=a+2;
mylinklist.add(shape2);
g.drawRect(x1-2, x2-2, a+4, a+4);
int[] shape3=new int[5];
shape3[0]=21;shape3[1]=x1-2;shape3[2]=x2-2;shape3[3]=a+4;shape3[4]=a+4;
mylinklist.add(shape3);
//调用square2绘制内部正方形
square2(a,x1,x2,count);
}
//用square2绘制内部的正方形(边框为白色)
public void square2(int a,int x1,int x2,int count){
//绘制中间第一个小正方形,用s表示小正方形边长
int s=a/3;
g.setColor(Color.BLACK);
g.fillRect(x1+s, x2+s, s, s);
int[] shape=new int[5];
shape[0]=31;shape[1]=x1+s;shape[2]=x2+s;shape[3]=s;shape[4]=s;
mylinklist.add(shape);
g.setColor(Color.WHITE);
//设置第一行小正方形的左上角坐标
int f1=x1;
int f2=x2;
int g1=x1+s;
int g2=x2;
int h1=x1+2*s;
int h2=x2;
//设置第二行小正方形的左上角坐标
int i1=x1;
int i2=x2+s;
int k1=x1+2*s;
int k2=x2+s;
//设置第三行小正方形的左上角坐标
int l1=x1;
int l2=x2+s*2;
int m1=x1+s;
int m2=x2+s*2;
int n1=x1+s*2;
int n2=x2+s*2;
//画出周围八个正方形
g.drawRect(f1,f2,s,s);
int[] shape8=new int[5];
shape8[0]=20;shape8[1]=f1;shape8[2]=f2;shape8[3]=s;shape8[4]=s;
mylinklist.add(shape8);
g.drawRect(g1,g2,s,s);
int[] shape1=new int[5];
shape1[0]=20;shape1[1]=g1;shape1[2]=g2;shape1[3]=s;shape1[4]=s;
mylinklist.add(shape1);
g.drawRect(h1,h2,s,s);
int[] shape2=new int[5];
shape2[0]=20;shape2[1]=h1;shape2[2]=h2;shape2[3]=s;shape2[4]=s;
mylinklist.add(shape2);
g.drawRect(i1,i2,s,s);
int[] shape3=new int[5];
shape3[0]=20;shape3[1]=i1;shape3[2]=i2;shape3[3]=s;shape3[4]=s;
mylinklist.add(shape3);
g.drawRect(k1,k2,s,s);
int[] shape4=new int[5];
shape4[0]=20;shape4[1]=k1;shape4[2]=k2;shape4[3]=s;shape4[4]=s;
mylinklist.add(shape4);
g.drawRect(l1,l2,s,s);
int[] shape5=new int[5];
shape5[0]=20;shape5[1]=l1;shape5[2]=l2;shape5[3]=s;shape5[4]=s;
mylinklist.add(shape5);
g.drawRect(m1,m2,s,s);
int[] shape6=new int[5];
shape6[0]=20;shape6[1]=m1;shape6[2]=m2;shape6[3]=s;shape6[4]=s;
mylinklist.add(shape6);
g.drawRect(n1,n2,s,s);
int[] shape7=new int[5];
shape7[0]=20;shape7[1]=n1;shape7[2]=n2;shape7[3]=s;shape7[4]=s;
mylinklist.add(shape7);
count--;
if(count<0) return;
//通过递归绘制谢尔宾斯基地毯
square2(s,f1,f2,count);
square2(s,g1,g2,count);
square2(s,h1,h2,count);
square2(s,i1,i2,count);
square2(s,k1,k2,count);
square2(s,l1,l2,count);
square2(s,m1,m2,count);
square2(s,n1,n2,count);
}
3、在paint()方法中调用事件处理类中队列的数据,根据表示图形种类的元素的值绘制图形
/**
* 重写JFrame中的paint方法
*/
public void paint(Graphics g){
super.paint(g);
for(int i=1;i<=Listener.mylinklist.size();i++){
ListNode array=Listener.mylinklist.getNode(i);
int[] a=array.getData();
if(a[0]==21){
g.setColor(Color.BLACK);
g.drawRect(a[1]+200,a[2],a[3],a[4]);
}else if(a[0]==31){
g.setColor(Color.BLACK);
g.fillRect(a[1]+200,a[2],a[3],a[4]);
}else if(a[0]==20){
g.setColor(Color.WHITE);
g.drawRect(a[1]+200,a[2],a[3],a[4]);
}
}
}