在画图板的实现那一节课中,我们发现我们所画出来的图形会在一段时间内慢慢消失,而且当把画图板最小化之后,画图板就会恢复成没画图形的样子(白板),我们知道,这是由于界面的重绘所致,为了解决这个问题,我们就应该给我们绘制的图形写一个重绘方法,但是,我们每次绘画图形的地点是不一样的,这就让我们想到用大型数组将我们画的图形存起来,但又有一个问题,再大的数组它也是有界的,当我们越界之后那不就出错了?这可怎么办呢?于是乎,我们学习了队列:
队列是设计程序中常用的一种数据结构。它类似日常生活中的排队现象,采用一种被称为“先进先出”(LIFO)的存储结构。数据元素只能从队尾进入,从队首取出。在队列中,数据元素可以任意增减,但数据元素的次序不会改变。每当有数据元素从队列中被取出,后面的数据元素依次向前移动一位。所以,任何时候从队列中读到的都是队首的数据。
根据这些特点,我们可以对队列定义以下五种操作(当然,肯定不止这五种,大家可以再去实现其它的操作):
从队列删除指定的一个对象
取得队列中指定位置的一个对象
删除指定index索引处的学生对象
向队列的index位置插入一个对象
向队列中加一个对象(加在末尾)
public class CustomListReal<E> implements CustomList<E>{ private Object []srcA = new Object [0]; /** * 向队列中加一个对象(加在末尾) */ public void add(E e) { //1.新建一个数组,长度为原数组长度+1 Object [] stuA = new Object [srcA.length+1]; //2.将要加入的对象放入新数组的最后一个位置 stuA[srcA.length] = e; //3.将原数组里的东西放到新数组中 for(int t = 0 ;t<srcA.length;t++){ stuA[t] = srcA[t]; } //4.将新数组赋给旧的 srcA = stuA; } /** * 向队列的index位置插入一个指定对象 */ public void add(E e, int index) { //1.新建一个数组,长度为原数组长度+1 Object [] stuA = new Object[srcA.length+1]; //2.在index以后的对象从后向前依次附给后面 for(int i = srcA.length; i>index; i--){ stuA[i] = srcA[i-1]; } //3.将要加入的对象放在index位置,index之前的对象保持不变 stuA[index] = e; for(int i = index-1; i>=0;i--){ stuA[i] = srcA[i]; } //4.将新数组附给旧数组 srcA = stuA; } /** * 删除index索引处的学生对象 */ public boolean delete(int index) { //1.新建一个数组,长度为原数组长度-1 Object [] stuA = new Object[srcA.length-1]; //2.将index后面的数依次赋给前面 for(int i = index; i<srcA.length-1;i++) stuA[i] = srcA[i+1]; //3.将要删除的对象放在index位置,index之前的对象保持不变 for(int i = index-1; i>=0;i--){ stuA[i] = srcA[i]; } System.out.println(srcA[index].toString().charAt(index)+"已被删除"); //4.将新数组附给旧数组 srcA = stuA; return true; } /** * 删除指定的一个对象 */ public boolean delete(E e) { boolean state = true; //1.新建一个数组,长度为原数组长度-1 Object [] stuA = new Object[srcA.length-1]; //2.遍历数组,找到要删除的对象 for(int i = 0;i<srcA.length;i++){ //如果找到 if(srcA[i] == e){ //将在i位置后面的数依次赋给前一个 for(int j = i;j<srcA.length-1;j++){ stuA[j] = srcA[j+1]; } //i前面的不变 for(int j = i-1;j >= 0;j--){ stuA[j] = srcA[j]; } //3.将新数组赋给旧的 srcA = stuA; state = true; }else{//如果没找到 state = false; } } if(state == true){ return true; } return false; } /** * 取得队列中指定位置的一个对象 *@return st 一个学生对象 */ public E get(int index) { E st = (E)srcA[index]; return st; } }
有了这些(其实只要有添加方法),我们就可以实现画图板图形的重绘了,把之前做的画图板调出来,将我们写的重绘方法添加进去就好了,举一个重绘直线的例子:
1.创建自定义队列的接口
/** * 自定义队列的接口 * @author Administrator */ public interface CustomList <E>{ //向队列中加一个对象 public void add(E e); }
2.创建自定义队列实现类
/** * 创建一个自定义队列的实现类,该类实现CustomList * @author ZhuMei */ public class CustomListReal<E> implements CustomList<E>{ private Object []srcA = new Object [0]; /** * 向队列中加一个对象 */ public void add(E e) { //1.新建一个数组,长度为原数组长度+1 Object [] stuA = new Object [srcA.length+1]; //2.将要加入的对象放入新数组的最后一个位置 stuA[srcA.length] = e; //3.将原数组里的东西放到新数组中 for(int t = 0 ;t<srcA.length;t++){ stuA[t] = srcA[t]; } //4.将新数组赋给旧的 srcA = stuA; } }
3.绘制直线的类:
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; /** * 绘制直线的类,该类继承自Shape抽象类 * @author ZhuMei * */ public class ShapeLine extends Shape { /** * 构造方法 */ public ShapeLine(int x1, int y1, int x2, int y2, Color color, int stroke) { super(x1, y1, x2, y2, color, stroke); } /** * 绘制图形的方法 */ public void draw(Graphics2D g) { g.setStroke(new BasicStroke(getStroke()));//设置线条粗细 g.setColor(getColor());//设置线条颜色 g.drawLine(getX1(), getY1(), getX2(), getY2()); } }
4.在监听器中绘制直线:
/** * 在事件源上发生鼠标释放的时候执行 */ public void mouseReleased(MouseEvent e){ x2 = e.getX(); y2 = e.getY(); if(db.getShapeType().equals("Line")){ g.drawLine(x1, y1, x2, y2); // 实例化一个绘制直线的方法 shape = new ShapeLine(x1, y1, x2, y2, Color.BLACK, 1); // 调用绘制图形的方法 shape.draw(g); cl.add(shape); }
5.在画板中实例化自定义队列的列表
private CustomList<Shape> cl = new CustomListReal<Shape>();
6 .在画板中重写重绘方法
public void paint(Graphics g){ super.paint(g); //遍历队列 for(int i=0;i<cl.size();i++){ Shape shape = cl.get(i); shape.draw((Graphics2D)g); } }
这样做了,我们画的直线就不会无缘无故的消失了,我们也可以用同样的方法实现其它图形的重绘了。不过还得解释一下E,这个是java中的泛型,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。当我们在这儿CustomList中使用之后,除了画板,其它的类型的队列是可以用的。
就写到这儿吧,编程,是应该在模仿中创新的,大家一起加油吧!
相关推荐
在本项目中,"VC++实现简单的画图板程序"是一个基础级别的计算机图形学应用,主要目的是让初学者了解如何使用Microsoft Visual C++ (VC++) 编程环境来创建一个功能丰富的图形用户界面(GUI)应用程序。这个程序允许...
在IT领域,C++是一种广泛使用的编程语言...通过使用std::vector作为底层实现,我们可以轻松地管理队列的动态大小,并实现所有必要的队列操作。这样的实现方式具有高度的灵活性和可复用性,是C++程序员必备的技能之一。
栈实现 队列实现 双栈实现队列 双队列实现栈 栈实现O(n)求当前栈最大值 http://blog.csdn.net/ssuchange/article/details/17398007
这通常意味着开发者在创建一个名为“我的画图板1.0”的应用程序时,正在为其基础架构进行规划,其中自定义队列是核心组件之一。自定义队列可能用于管理用户的绘画操作,如绘制顺序、撤销/重做功能或处理图像处理任务...
以上是关于"循环队列 C++不同策略模板实现"的详细知识点介绍,通过这样的实现,我们可以创建高效且灵活的队列结构,适应各种场景的需求。在实际编程中,理解和掌握这些知识对于提高代码质量和效率至关重要。
循环队列是一种线性数据结构,它在物理结构上实现了一个闭合的循环,因此队首和队尾可以在数组的任意位置。这种设计使得在队列满或空时,仍能有效地进行入队和出队操作,避免了普通队列在达到边界条件时的特殊处理。...
在C++中,我们可以利用STL(Standard Template Library)中的`queue`容器来实现队列,但为了理解队列的工作原理并实现自己的模板队列,我们需要手动创建一个模板类。以下是一个基本的模板队列实现: ```cpp #...
在本项目中,我们探讨的是如何使用Microsoft的Visual C++(VC++)集成开发环境和MFC(Microsoft Foundation Classes)库来构建一个简单的画图板应用程序。MFC是微软提供的一套C++类库,用于简化Windows应用程序的开发,...
### 数据结构:队列实现详解 #### 一、队列概念与特性 在计算机科学领域,**队列**是一种常见的线性数据结构,遵循先进先出(First In First Out, FIFO)的原则。也就是说,最早添加到队列中的元素将是最先被移除的...
在C++中,标准库提供了一个名为`deque`的容器,但在这里,我们讨论的是一个自定义实现的基于数组的双端队列类模板。 在C++编程中,类模板(Class Template)是泛型编程的一种形式,允许创建可适用于不同数据类型的...
队列是一种特殊的线性数据结构,它遵循“先进...此外,链表实现的队列在处理大量数据时,由于需要频繁地创建和销毁节点,其效率可能会低于数组实现的队列。因此,选择哪种实现方式应根据具体应用场景和性能需求来决定。
顺序队列和链式队列的实现 在计算机科学中,队列是一种重要的数据结构,广泛应用于多种领域。在本节中,我们将讨论顺序队列和链式队列的实现。 顺序队列 顺序队列是一种基于数组的队列实现方式。其主要特点是使用...
它通过将任务放入队列中,然后由一个或多个工作线程按顺序取出并执行,有效地实现了任务的异步处理和调度。下面将详细讨论如何实现C#任务队列及其相关知识点。 1. **线程安全**: - 在多线程环境下,对任务队列的...
然而,如果你想要自定义一个双端队列,我们可以从头开始探讨如何实现。 自定义双端队列的基本思想是使用动态数组或链表作为底层数据结构。这里我们以动态数组为例,因为它提供了更好的空间效率和随机访问性能。一个...
在Java中,队列的实现主要有三种:顺序队列、链式队列和循环队列。下面我们将详细探讨这三种队列的实现方式。 1. **顺序队列**: 顺序队列通常是基于数组实现的。在Java中,我们可以使用ArrayList或LinkedList来...
【高效延时队列的设计与实现】 延时队列是一种特殊的消息队列,它具有延时功能,使得消息在生产者发布后不会立即被消费,而是会在预设的延时时间过后才被处理。这种机制在很多业务场景中非常有用,如订单处理、定时...
循环队列是一种线性数据结构,它在物理结构上实现了一个首尾相接的闭合序列,从而解决了普通队列在满和空时的操作限制。循环队列的主要优点是消除了队头和队尾的特殊状态,使得在处理数据时效率更高。下面将详细介绍...
优先队列是一种特殊的数据结构,它允许我们按照...总的来说,这个压缩包提供了一个用C语言实现的基于堆的优先队列,包含了实现和测试的源码,以及使用说明,是学习和理解优先队列及其底层数据结构堆的一个实用资源。
使用c++模板实现的堆排序、优先级队列,在vs2010下编译运行通过。压缩文件里为两个工程文件,如果有vs2010的话解压缩打开sln文件就可以了,没有的话,新建工程将文件复制过去就ok了。如果有问题可以留言。
在C++中,循环队列通常用数组实现,通过两个指针分别指向队头和队尾,队列的入队(enqueue)和出队(dequeue)操作可以通过简单的指针移动来完成,避免了数组扩容的开销。 最后,我们讨论链队列。链队列是基于链表...