Java小程序之自定义数组队列的实现(高级画板重绘基础)

Java小程序之自定义数组队列的实现(高级画板重绘基础)

前言:经过一番努力,我们的画板已经完成了很大一部分,很多功能都已经通过我们自己的分析和代码实现了,但是还是有小bug呢?你找到小bug了吗?当我们绘制好图形后,点击窗体的最小化,然后最大化,会发现我们绘制的图形全都没有了,机智的你发现了吗?那么该怎么解决这个bug呢?让我们先来看看自定义数组队列相关知识吧!


知识回顾:

1、一维数组

定义格式:  类型[] 数组名 = new 类型[长度];
                  类型[] 数组名 = {值,值,值.....};
                  类型[] 数组名 = new 类型[]{值,值,值.....};     
                                  
取值格式:类型 变量名 = 数组名[索引下标];
赋值格式:数组名[索引下标] = 值;
获取数组长度:数组名.length
遍历数组:结合循环遍历(for)

2、二维数组

定义格式:   类型[][] 数组名 = new 类型[行数][列数];

                  类型[][] 数组名 = {{值,值,....},{值,值,....},{值,值,....},.....};
                  类型[] 数组名 = new 类型[]{{值,值,....},{值,值,....},{值,值,....},.....};;     
                                  
取值格式:类型 变量名 = 数组名[行索引][列索引];
赋值格式:数组名[行索引][列索引] = 值;
获取数组总行数:数组名.length
获取数组总列数:数组名[某一行索引].length

遍历数组:结合循环遍历(for)


3、数组的优缺点

      数组有很多的优点:比如存储方便,很容易访问等;但数组有一个很大的缺点,那就是定义数组时必须事先知道数组的大小,对于存储未知个数的值很不方便,数组开小了,很可能存不下,数组开大了,可能会浪费很大的空间,如果有一种数据结构,能够动态的添加或者删除元素,你有多少个变量,我就给你开多大的空间,这样就完美的解决了数组所带来的问题;现在,我们就要自己实现这样一种数据结构;


自定义队列实现思路:

(添加元素功能)

1、定义一个初始大小为0的数组;

2、当需要往里面添加元素时,产生一个新数组,新数组的长度在原来数组的基础上加1;

3、把新数据存进最后的空间

4、把原数组的数据拷贝到新数组

5、把新数组的地址给原数组


(插入元素功能)

1、当需要往里面插入元素时,产生一个新数组,新数组的长度在原来数组的基础上加1;

2、根据插入位置将元素插入指定位置

3、把插入位置前的原数组的数据和插入位置后的原数组的数据拷贝到新数组中

4、把新数组的地址给原数组


删除功能、更新功能类似;

示意图:






源代码:

接口类:规范子类必须实现的方法

package com.huaxin.zhou;

public interface ListInterface {

	public void add(String value);//添加元素的方法
	public void delete(int index);//删除指定位置元素的方法
	public void update(String value,int index);//将指定位置的值进行更新
	public void insert(String value,int index);//在指定位置插入元素
	public int size();//得到队列的大小
	public String get(int index);//拿到队列中的某一个元素
}


子类具体的实现:

package com.huaxin.zhou;

public class MyList implements ListInterface{

	private String[] containt = new String[0];

	//新增操作
	public void add(String value) {
		//定义一个比原数组长1的新数组
		String [] newContaint = new String[containt.length+1];
		//把值赋给新数组的最后
		newContaint[newContaint.length-1]=value;
		//把原数组的元素进行拷贝
		for(int i=0;i<containt.length;i++){
			newContaint[i]=containt[i];
		}
		//把原数组指向新数组的地址
		containt=newContaint;
		
	}

	//删除操作
	public void delete(int index) {
		
		//新定义一个比原数组少1的新数组
		String [] newContaint = new String[containt.length-1];
		
		//把插入位置前的元素进行拷贝
		for(int i=0;i<index;i++){
			newContaint[i]=containt[i];
		}
		
		//把插入位置后的元素进行拷贝
		for (int i= index+1; i < containt.length; i++) {
			newContaint[i-1]=containt[i]; 
		}
		
		//把原数组指向新数组的地址
		containt=newContaint;
		
		
	}

	//更新操作
	public void update(String value,int index) {
		//把新的值赋值把指定位置的值
		containt[index]=value;
		
	}

	//插入操作
	public void insert(String value, int index) {
		
		//新增比原数组长1的新数组
		String [] newContaint = new String[containt.length+1];
		
		//把新元素插入到新数组指定的位置
		newContaint[index]=value;
		
		//把插入位置前的原数组的元素进行拷贝
		for(int i=0;i<index;i++){
			newContaint[i]=containt[i];
		}
		
		
		//把插入位置后的原数组的元素进行拷贝
		for (int i = index+1; i < newContaint.length; i++) {
			newContaint[i]=containt[i-1];
		}
		
		//把原数组指向新数组的地址
		containt=newContaint;
		
	}

	public int size() {
		return containt.length;
	}

	

	public String get(int index) {
		return containt[index];
	}

}


测试类:

package com.huaxin.zhou;

public class Test {
	
	public static void main(String[] args) {
		
		//测试天机元素的功能
		MyList list = new MyList();
		list.add("zhou");
		list.add("Blue");
		list.add("Sky"); 
		//测试得到队列大小的工嗯呢该
		System.out.println(list.size());
		//查看队列中的元素
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
		
		//更新元素功能
		list.update("blue",1);
		
       //查看更新是否成功
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
		//插入元素功能
		list.insert("hello", 2);
		
		//查看是否插入成功
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
		//删除元素功能
		
		list.delete(2);
		
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
	}
	
	

}


运行结果:



到这里,我们的自定义队列就实现了,是不是很方便,这样可以动态的管理;


这里,我们学到了队列试下的底层原理,其实Java中已经帮我们实现了这一数据结构,那就是Java中ArrayList类;


这种数据结构就好比一个容器,我可以往里面装很多东西,容器可以随着你装东西的多少而动态的变化;


好了,怎么把这种结构用来我们的画板中,进行图形的重绘呢?

这里,我们还需要了解一下:我们的数据是存储在硬盘上的,当前运行的程序是在内存中的,而在屏幕上显示的是存储在缓冲中,当我们点击最小化时,缓冲数据会被清除,所以在点击最大化时,绘制的图形才没有了;那为什么窗体甚至窗体上的按钮还在呢?因为窗体和窗体上的按钮在内存中有数据(我们在Java中用new创建了这下对象,但画笔绘制的直线并没有创建),当最大化时,缓冲会从内存中重新加载这些数据,所以窗体和按钮自然就会在那里了;




明白了这个,那么我们就可以进行画板的重绘了,只要把屏幕上的绘制的这些图形进行保存,当窗体最大化时,重新绘制这些直线就可以了(窗体最大化时,会调用对象的paint方法,所以,我们在paint方法进行直线重绘)


以前面画板基础入门为例,进行直线的重绘,高级画板会复杂一点,要进行多种图形的重绘,颜色的重绘等;在后面的博客中会有,敬请期待!



源代码:(参看前面的Java小程序之简单画板入门博客)

(新创建直线类)

package com.huaxin;

public class Line {

	public  int x1;
	public int y1;
	public int x2;
	public int y2;
	
	public Line(int x1,int y1,int x2,int y2){
		this.x1=x1;
		this.y1=y1;
		this.x2=x2;
		this.y2=y2;
	}
}



每绘制一条直线,产生一个直线对象,并将直线对象装嫩容器中
package com.huaxin;

import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;


public class DrawListener implements MouseListener{
	
	public Graphics g;
	public int x1,y1,x2,y2;
	
	public ArrayList list;
	
	public DrawListener(){
		
	}
	
	//这里拿到的画笔是DrawBoard里面的画笔的地址
	public DrawListener(Graphics g1,ArrayList list){
		g=g1;
		this.list=list;
	}
	
	public void mousePressed(MouseEvent e) {
		x1=e.getX();
		y1=e.getY();
	}

	public void mouseReleased(MouseEvent e) {
		x2=e.getX();
		y2=e.getY();
		g.drawLine(x1, y1, x2, y2);
		//将绘制的直线生成直线对象进行保存
		Line line = new Line(x1, y1, x2, y2);
		//将直线保存到容器中
	    list.add(line);
		
	}

	public void mouseClicked(MouseEvent e) {
		
	}

	public void mouseEntered(MouseEvent e) {
		
	}

	public void mouseExited(MouseEvent e) {
		
	}


}

直线重绘:
package com.huaxin;

import java.awt.Graphics;
import java.util.ArrayList;

import javax.swing.JFrame;


public class DrawBoard extends JFrame{
	
	//容器类,装直线对象
	public ArrayList list = new ArrayList();
	
	public static void main(String[] args) {
		  
		DrawBoard bd = new DrawBoard();
		bd.initFrame();
		
		
	}
	
	
    //重新绘制方法
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <list.size(); i++) {
			Line line =(Line)list.get(i);
			g.drawLine(line.x1,line.y1,line.x2,line.y2);
		}
	}
	
	
	public void initFrame(){
		//设置窗体相关属性
		this.setSize(600,500);
		this.setTitle("简易画板");
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		
		//获取窗体的画笔(注意:必须得在设置窗体的可见性之后才可以拿到画笔)
		Graphics g = this.getGraphics();
		DrawListener ml = new DrawListener(g,list);//传递的是画笔的地址,联系前面内存中的堆栈
		this.addMouseListener(ml);
	}

}


运行结果:





最小化后直线还是存在的哟!好了,问题到这里就解决了!


总结:

1、深刻的理解了队列底层原理(容器)

2、知道该怎样进行重绘,以及重绘的原理;

3、一定要把自定义队里代码敲一遍,原理可能谁都听得懂,但要你自己实现,并一定每个人都能实现;

4、多动手,多积累!共勉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值