`
御天田
  • 浏览: 14593 次
  • 性别: Icon_minigender_2
文章分类
社区版块
存档分类

队列和队列重绘----简单画图板的实现

阅读更多
队列和队列重绘
自定义队列:
在谈自定义队列之前,我们要清楚一个问题就是------“数组”的优点和缺点有哪些,优点当然有很多,但是,当我们所需要存储的数据元素个数不定时能用数组来存储吗?不行!当我们需要存储的对象类型不定或者有多种类型的时候能用到数组吗?不行!这个时候就需要自定义队列啦!
自定义队列的思路:
首先在实现类的内部还是使用数组来保存装入队列的对象,每次新加入对象时,则再创建一个比原来数组长度大1的数组,再将新数组的地址赋给原来的数组,这样就可以想存多少就存多少啦!我们来通过下面的例子来说明:


//实例化一个学生对象的数组 arr[],长度为0 ,Student是已经创建的一个学生类 private Student[] arr=new Student[0];
//定义一个size属性,用来表示队列中的元素个数
private int size=0;
/**
* 添加一个新元素,参数stu是要被储存的对象
*/
public void add(Student stu){
//实例化一个新的数组,数组长度是原来数组长度+1
Student[] stud=new Student[arr.length+1];
//将原数组中的数据放到新数组中去
for(int i=0;i<arr.length;i++){
stud[i]=arr[i];
}
//将要新加的元素stu加到新数组stud的后面
stud[arr.length]=stu;
//将新数组的首地址赋给原数组
arr=stud;
size++;
}
以上就是自定义队列的用法啦!
那么当我们存储的类型时多种类型时,又应该在怎样做呢?
别忘了java中所有引用数据类型的父类是Object,那么我们在定义数组类型的时候将它定义成Object类型,然后每个方法指定的类型也为Object就行啦!
这里我们容易想到另一个问题,要是我要数组有时只存一种数据类型有时又要存多种数据类型,又该怎么存呢?
这个时候我们就要用到传说中的“泛型”了。泛型----是实用一个E来表示的(注意!这里的E只表示类,不能用来表示基本数据类型(8大基本数据类型))如果想在使用了泛型的队列中存储8大基本类型的值,可以使用它们各自的封装类(在java.lang.*中都可以找到),下面我们来看一个使用泛型的例子:


public class Queue<E> {
//实例化一个数组 arr[],长度为0
private Object [] arr=new Object[0];
//定义一个size属性,用来表示队列中的元素个数
private int size=0;
/**
* 添加一个新元素,参数e是要被储存的对象
*/
public void add(E e){
//实例化一个新的数组,数组长度是原来数组长度+1
Object[] tempArray =new Object[arr.length+1];
//将原数组中的数据放到新数组中去
for(int i=0;i<arr.length;i++){
tempArray[i]=arr[i];
}
//将要新加的元素e加到新数组tempArray的后面
tempArray[arr.length]=e;
//将新数组的首地址赋给原数组
arr=tempArray;
size++;
}
注意:当我们用要指定其为某种格式时,格式应该是:
private static Queue<Shape> qd = new Queue<Shape>();//Queue指定为Shape型,实例化一个队列qd的对象

相信大家看了上面的例子,“泛型”这个东东其实不抽象吧。
队列重绘:
理解了自定义队列后,队列的重绘操作也就简单啦!我们还是先来看看在画图板中实用数组进行重绘时的操作:


         //创建一个画布面板panelC
JPanel panelC = new JPanel(){
//重写panel中的重绘方法,g是画布
public void paint(Graphics g){
//先调用父类中的paint方法,系统式自动设置其父类为Object,
           不用我们手动继承
super.paint(g);
//将监听器中获得到图像的像素点坐标(x,y)赋给二维数组arr[][]
         int arr[][]=ButtonLitener.getArr();
if(arr!=null){
//通过循环取得数组中的坐标点
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
//通过Color对象将像素点转换成对应的颜色
Color color=new Color(arr[i][j]);
//调用setColor方法,给画布添加颜色
g.setColor(color);
//调用drawLine方法绘制点,因为图像实际上是由点组成的,
                      注意画的是点,所以画直线的起始坐标和终点坐标是一样的
           g.drawLine(i, j, i, j);
}
}
}
}
};
如果我们使用队列重绘就不用这样写啦!因为实际上我们在用数组进行重绘时,是存储了整个画布,但如果使用自定义队列,因为自定义队列有长度可以随增的优点,我们可以只存我们画的单个图像,而不用存整个画布了。
那么 为什么可以用队列来实现画图板的重绘呢?还是先来看看代码:
//创建一个画布面板
JPanel panelC = new JPanel(){
//重写父类的paint方法
public void paint(Graphics g){
//先调用父类的paint方法
super.paint(g);
//创建一个shape类型的队列(队列使用的是泛型),
           得到监听器中用来存放我们画的图形的队列
Queue<Shape> qd=ButtonLitener.getQ();
//循环取得队列中存放的每一个shape
for(int i=0;i<qd.getSize();i++){
Shape shape=qd.get(i);
//通过调用draw方法将图重新画出来
shape.draw((Graphics2D) g);
}
看完代码后,如果你知道用数组来对画图板进行重绘的原理就不难理解用队列来重绘画图板了,因为在数组中我们存放的是画图面板的每个像素点,再通过遍历每个坐标来重新绘制画图板,而用队列实现重绘时,队列里面实际上存放的是每个Shape对象,这里所说的shape是一个抽象类,它的构造方法是:
//声明起始点坐标x1
private int x1;
// 声明起始点坐标y1
private int y1;
// 声明结束点坐标x2
private int x2;
// 声明结束点坐标y2
private int y2;
// 声明设置线条粗细的对象
private Stroke stroke;
//  声明设置颜色的属性
private Color color;
public Shape(int x1, int y1, int x2, int y2, Color color,Stroke stroke) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.stroke = stroke;
this.color=color;
}
当然,要完成画图板的重绘操作光靠这些是不行的,我们必须在监听器中运用队列或者是数组来存放我们画的图像,只不过用自定义队列来存放的话会给我们带来很大的方便。后面附上了用队列对画图板进行重绘的代码,希望大家多多提出好的建议呀!
  • .jar (9.3 KB)
  • 下载次数: 4
  • .jar (4.4 KB)
  • 下载次数: 1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics