`
茖-荌
  • 浏览: 31298 次
社区版块
存档分类
最新评论

图像重绘

阅读更多

一、为什么要重绘

1、计算机有三种存储数据的存储器--外存、内存和缓存。缓存就是计算机里的硬盘,外存的特点 是可以永久地保存数据(在硬盘不会损坏的情况下),它的缺点是:存储数据和读取数据的速度 很慢。内存是介于外存与缓存之间,计算机所要运行的所有程序,必须先从外存读取到内存中, 这当然也包括操作系统。还有内存在通电状态下才有保存数据的作用,如果计算机的电源关闭了 ,内存里的数据也会消失,所以我们在做一些重要的文档时要及时保存数据,这里的保存是将内 存里的数据保存到外存里,也就是硬盘上。缓存是CPU上的一块存储器,它是用来临时保存CPU马 上要处理的数据,一旦里面的数据不需要了,缓存就会马上被清空。

2、我们在画图板上画的图形,它的数据是被临时保存在缓存里的,当我们把窗口最大化或最小化, 或其他的操作是,缓存里的数据就会被清空。而当我们再把窗口还原是,窗口的数据会重新从内存读 到缓存里,经过处理后吧窗体显示,但是因为我们没有把我们画的图形的数据保存起来,所以当窗体 重新显示时,我们之前画的图形并没有显示。所以要让我们画的图形能够重新显示,我们必须把图形 的数据保存起来。

二、重绘的方法

1、用队列来保存数据 队列是用来保存数据的一种数据结构,它相当于一个动态数组,所以我们可以用它来保存我们 在画图板上所画的图形的数据。思路就是我们每画一个图形,就把它保存到队列里去,当需要重 绘时,只需要把队列里的数据重新取出来,把它画到画图板上。

下面是我自定义的保存图形数据 的队列:

     public class mylist<E> {
	//将数组定义为Object数组,表示能存放Java中所有的对象
	private Object[] src = new Object[0];
	/**
	 * 将指定的数据放入队列容器中
	 * 
	 * @param e
	 *            要放入队列容器的数据
	 */
	public void add(E e) {
		//定义一个新数组,长度是原始数组长度+1
		Object dest[] = new Object[src.length+1];
		
		//将新元素放入新数组最后一个下标位置
		dest[src.length] = e;
		//将原始数组中的元素按照下标顺序拷贝到新数组
		for(int i=0;i<src.length;i++){
			dest[i] = src[i];
		}
		
		//将原数组名指向新数组
		src = dest;
	}

	/**
	 * 取出指定下标位置的元素
	 * 
	 * @param index
	 *            要取出的元素的下标
	 * @return 返回取得的元素
	 */
	public E get(int index) {
		//得到src对应下标的元素
		E e = (E)src[index];
		return e;
	}

	/**
	 * 删除指定位置的元素
	 * 
	 * @param index
	 *             要删除的元素的下标
	 */
	public void delete(int index) {
		//创建一个长度比src小1的数组
		Object [] arr =new Object[src.length-1];
		//拷贝下表之前的元素
        for(int i=0;i<index;i++){
        	arr[i]=src[i];
        }
        //拷贝下标之后的元素
        for(int j=index;j<src.length;j++){
        	arr[j]=src[j+1];
        }
        //修改后让src指向arr
        src=arr;
	}

	/**
	 * 将指定位置的元素修改为指定的值
	 * 
	 * @param index
	 *            要修改的元素的下标
	 * @param num
	 *            修改之后的新值
	 */
	public void modify(int index, E e) {
		src[index] = e;
	}

	/**
	 * 在指定的位置插入指定的元素值
	 * 
	 * @param index
	 *            要插入元素的位置
	 * @param e
	 *            要插入的元素
	 */
	public void insert(int index, E e) {
       //创建一个比src大1的数组
	    Object [] arr =new Object[src.length+1];
	    //拷贝添加的元素下标之前的元素
	    for(int i=0;i<index;i++){
	    	arr[i]=src[i];
	    }
	    //添加要插入的元素
	    arr[index]=e;
	    //拷贝添加元素下标之后的元素
	    for(int j=index;j<arr.length;j++){
	    	arr[j+1]=src[j];
	    }
	    //让src重新指向arr
	     src=arr;
	}

	/**
	 * 得到容器中元素个数的方法
	 * 
	 * @return 返回容器中的元素个数
	 */
	public int size() {
		//队列长度就是src数组的当前长度
		int len = src.length;
		return len;
	}
     }

  还有一个用来保存图形相关信息的一个类:

 public class myshape {
	   //定义形状的属性
        private byte type;
        //保存坐标的属性
        private int x1,y1,x2,y2;
        //设置颜色属性
        private Color color;   
        //设置形状的方法        
        public void setShape(byte type){
        	this.type=type;
        }
        //获取形状的方法
        public byte getShape(){
        	return type;
        }
        //给坐标赋值的 方法
        public void setvalue(int x1,int y1,int x2,int y2){
        	this.x1=x1;
        	this.y1=y1; 
        	this.x2=x2;
        	this.y2=y2;
        }  
     
        //获取x1坐标值的方法
        public int getx1(){
        	 return x1;      
        }  
        //获取y1坐标值的方法
        public int gety1(){
        	 return y1;      
        }  
        //获取x2坐标值的方法
        public int getx2(){
        	 return x2;      
        }  
        //获取y2坐标值的方法
        public int gety2(){
        	 return y2;      
        }  
      //定义设置颜色的方法
        public void setcolor(Color color){
        	this.color=color;
        }
      //定义获得颜色的方法
        public Color getcolor() {
    		return color;
        }
     } 

 重绘部分的代码

	  //在调用子类重写了的方法时,需要先调用父类中原有的方法???
	  public void paint(Graphics g) {
		    super.paint(g);//调用父类中的方法
		 
		  //把原来画的东西,自己写代码,再画出来!
		  //获得队列对象
		  mylist mlis=drl.getMylist();
		  for(int i=0;i<mlis.size();i++){
			  //获得队列中的元素
			  Object ms=mlis.get(i);
			  //强制转换为myshape类型
			  myshape sp=(myshape)ms;
			  //画直线
			  if(sp.getShape()==1){
				  //设置颜色
				  hb.setColor(sp.getcolor());
				  hb.drawLine(sp.getx1(), sp.gety1(), sp.getx2(), sp.gety2());
			  }
			 //画圆
			  if(sp.getShape()==2){
				  //设置颜色
				  hb.setColor(sp.getcolor());
				  hb.drawOval(sp.getx1(), sp.gety1(), sp.getx2(), sp.gety2()); 
			  }
			  //画矩形
			  if(sp.getShape()==3){
				  //设置颜色
				  hb.setColor(sp.getcolor());
				  hb.drawRect(sp.getx1(), sp.gety1(), sp.getx2(), sp.gety2()); 
			  }
			  // 话填充矩形
			  if(sp.getShape()==4){
				  //设置颜色
				  hb.setColor(sp.getcolor());	  
			      hb.fillRect(sp.getx1(), sp.gety1(), sp.getx2(), sp.gety2()); 
		      }
		      //画填充圆
			  if(sp.getShape()==5){
				  //设置颜色
				  hb.setColor(sp.getcolor());
				  hb.fillOval(sp.getx1(), sp.gety1(), sp.getx2(), sp.gety2()); 
			  }
		  }
	  }

 用这种方法进行重绘,十分严重的问题是当画的形状过多时,队列里面会保存大量的数据,而很多又是不需要的,所以我们得用另一种方法来重绘

2、用数组来保存数据 数组怎么用来保存图形的信息呢?

首先,让我们先了解一下计算机屏幕显示图像的原理。我们在 屏幕上看到的图像其实是有一个个像素点组成的,每个像素点可以显示不同的颜色,于是不同颜色 的像素点有机的组合在一起,便形成了丰富多彩的图像。根据这一点,想想如果我们能把屏幕上的 每个像素点的颜色信息保存起来,不就能把画图板上的图像信息保存了吗。而像素点的颜色值可以 用一个整数来表示,又画图板是一个矩形区域,所以用一个二维数组来保存是最合适的。

下面是保存画图板上每个像素点的颜色值的主要代码:

// 获取drawPanel左上角的相对于屏幕的位置
		Point point = drjp.getLocationOnScreen();
		// 获取drawPanel的大小
		java.awt.Dimension dim = drjp.getPreferredSize();

		// 创建一个要截取的区域对象(就是drawPanel所占据的区域)
		java.awt.Rectangle rect = new java.awt.Rectangle(point, dim);

		// 绘制完一个图像就截屏
		BufferedImage img = robot.createScreenCapture(rect);

		// 根据图像创建二维数组
		data = new int[img.getHeight()][img.getWidth()];		
		// 将图像上的每一个点的颜色存储到数组中
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data[i].length; j++) {
				int rgb = img.getRGB(j, i);
				// 将坐标和下标对应保存颜色
				data[i][j] = rgb;
			}		
		}		
 

 

 

分享到:
评论
1 楼 JoeBaby_ 2012-08-15  
good,原来不是很难的说

相关推荐

    图像重绘频域算法(又称风格迁移)

    图像重绘频域算法,又称为风格迁移,是计算机视觉领域的一个重要研究方向,它涉及到图像处理、机器学习,特别是深度学习技术。该算法的主要目标是将一张图像的内容与另一张图像的风格相结合,创造出全新的视觉效果。...

    VC++对话框程序picture控件图像重绘

    要实现图像重绘,你需要覆盖对话框类的`OnPaint()`函数。`OnPaint()`函数在窗口需要更新时被调用,我们可以在这里进行自定义绘制。但需要注意,picture控件通常不直接支持重绘,因为它是静态控件。你可以考虑两种...

    VC++对话框程序picture控件图像重绘+详细说明文档

    本教程将深入讲解如何在对话框中使用Picture控件来显示图像,并实现图像的重绘功能。这对于任何希望在MFC应用中处理图形的初学者来说都是一份宝贵的学习资料。 首先,我们需要了解`CStatic`类,这是MFC用于创建静态...

    MFC 基本常用控件重绘

    在本文中,我们将深入探讨如何在MFC中重绘常见的控件,包括ListCtrl、Edit和ComboBox,这些都是Windows应用程序开发中的关键组件。 **ListCtrl控件** ListCtrl是一种多功能控件,它可以显示多列数据,类似于电子...

    用MFC对话框做无闪烁图片重绘

    其中,“无闪烁”图像重绘是一种提升用户体验的关键技术,特别是在用户调整窗口大小时,能够平滑地更新图像而不出现闪烁现象,显得尤为重要。本文将通过一个具体示例来讲解如何利用MFC对话框实现无闪烁的图片重绘。 ...

    窗体控件重绘

    1. **Button控件重绘**:Button控件的重绘通常涉及到改变按钮的背景色、边框样式、文字颜色以及添加自定义图像。通过重写`OnPaint`事件,我们可以使用`Graphics`对象进行精确的绘制,如使用`FillRectangle`填充背景...

    winform gdi+重绘窗体 控件

    本文将深入探讨如何使用C#和GDI+来实现Winform窗体及控件的重绘功能,包括button、listbox、checkbox等常见控件,以及换肤的概念。 1. **Winform窗体的重绘** - Winform窗体的重绘通常涉及到`OnPaint`事件。当窗体...

    MFC CListCtrl重绘,功能全

    在某些情况下,为了实现更复杂或个性化的界面效果,我们可能需要对CListCtrl进行重绘。本篇将深入探讨CListCtrl的重绘机制和如何实现全面的功能。 首先,理解CListCtrl的绘制过程至关重要。CListCtrl默认使用...

    C# TreeView重绘边框

    本文将深入探讨如何在C#中实现`TreeView`控件的边框重绘,以创建独一无二的视觉效果。 首先,了解`TreeView`的基本属性和方法。`TreeView`控件具有`Nodes`集合,用于添加、删除或操作节点;`DrawMode`属性可以设置...

    重绘 C# button按钮

    本节将详细介绍如何通过重绘技术实现自定义的C#按钮。 首先,理解WinForms中的控件绘制原理至关重要。Windows Forms控件,包括Button,都是基于GDI+图形接口进行绘制的。默认情况下,系统会自动处理控件的绘制,但...

    GDI与GDI+图像显示处理

    在描述中提到的“图像重绘的问题”,在GDI和GDI+中,通常涉及到OnPaint成员函数的实现,这里需要正确地响应WM_PAINT消息,使用双缓冲技术可以避免闪烁,提高用户体验。双缓冲是指在内存中创建一个位图,先在这个位图...

    控件重绘 C# WinForm控件美化扩展系列之TabControl

    "控件重绘 C# WinForm控件美化扩展系列之TabControl"的主题聚焦于如何通过自定义控件重绘技术来优化TabControl的显示效果,使其更符合现代应用程序的审美需求。 TabControl是Windows Forms中一个常用且功能丰富的...

    MFC控件CTabCtrl的重绘,支持背景颜色、tab头字体颜色、背景色的修改

    重绘过程中,为了保持性能,可以利用Windows的消息机制,只在必要时(如tab切换、窗口大小改变等)才触发重绘。可以通过`SetRedraw`函数暂时关闭或开启控件的重绘功能,这样可以避免不必要的绘图操作。 除了`...

    按钮,列表框重绘.按钮,列表框重绘

    在编程领域,特别是GUI(图形用户界面)设计中,按钮和列表框的重绘是两个重要的概念。这些组件是用户与应用程序交互的主要方式,因此它们的外观和行为必须符合用户的期望,并能根据需要动态更新。下面我们将深入...

    C# 重绘文本框

    但在标准的文本框上,我们无法直接修改其内部渲染过程,如改变文本颜色、添加背景图像等,这就需要我们进行重绘。 ### 2. 重绘机制 在C#中,我们可以利用控件的`OnPaint`方法来进行重绘。当控件需要刷新时,系统会...

    CListCtrl控件重绘类

    然而,有时我们需要自定义CListCtrl的行为,比如改变其默认的外观或增加特定功能,这就涉及到CListCtrl的重绘类。 "重绘类"是指开发者创建的一个派生自CListCtrl的自定义类,它扩展了CListCtrl的原生功能,以便实现...

    C#复选框重绘 Checkbox

    本教程将深入探讨如何在C#中实现`Checkbox`的重绘,以实现这些高级功能。 首先,我们需要了解Windows Forms中的控件绘制机制。每个Windows Forms控件都有一个`OnPaint`事件,当控件需要更新其外观时,系统会触发这...

    JAVA中的控件重绘

    在重绘过程中,可能用到此类来动态生成或修改显示的图像。 - `TestMenu.java`:测试菜单类,可能包含了对Java菜单组件的测试代码,包括添加菜单项、监听事件以及测试重绘效果。 - `CubeMenuItem.java`、`CubeMenu....

    MFC单文档界面的全部重绘

    在实现界面重绘时,可能需要使用到图像资源,例如背景图片、按钮图标等。这些资源通常存储在资源文件(如.rc)中,通过LoadBitmap()或LoadCursor()等函数加载。此外,还可以考虑使用皮肤系统,如wxWidgets或Qt,...

    解决重绘时候闪屏问题的实例程序

    在计算机图形学和用户界面设计中,"闪屏"是一个常见的问题,特别是在应用程序进行重绘时。这通常表现为屏幕上的内容快速闪烁或者不连续的变化,影响用户体验。本实例程序主要针对这个问题提供解决方案,旨在帮助...

Global site tag (gtag.js) - Google Analytics