上一篇所总结的是实现画图板的界面以及基本功能。那么在我们画图的时候就会发现一个问题:我们画好了一个图形之后,如果改变的窗口大小,或者最大化最小化之后,我们所画的图形就都消失了!我们画的东西之所以会小时,是因为我们没有将所画的形状存放到内存中。而且我们在执行上述操作(改变窗体大小……)的时候会自动调用一个paint的方法。我们没有定义重绘paint的这个方法,所以在执行重绘的时候之前所画的都不存在了。所以使得自己所画图案永久存在的方法就是要在执行paint方法的时候再把我们所画的图案给他重新画一遍!这就是重绘。
重绘的方法有很多,我现在也只是能够完成使用一维数组或者二维数组这两种方法来进行重绘操作。
一维数组的重绘
一维数组确实可以完成重绘方法,但很麻烦很麻烦而且又不稳定。这总结他只是简单的说下吧,因为他不实用。
我们在画图的时候最关键的几个要素就是:画什么,在哪里画,颜色。这三点,在哪里画的关键则是所取得的那些xy坐标。所以只要我们使用一个一维数组把所画图形坐标都给存储起来,再重绘的方法中再按照存储起来的坐标给重新绘制一遍,就完成了重绘的操作。只用直线举个例子吧:
新建一个一维数组 int [] array_line = new int[];那么我们在建立数组的时候发现问题了:数组长度设置为多少呢??这就是之前所说一维数组完成重绘的缺点,不仅仅是麻烦,而且如果我们在这里数组长度定义的较小,例如定义为100。那么我们存储25条直线之后再画的先就存储不下了。若是定义的过大则是对内存的浪费。。
先不管那些啦。看看一维数组怎样存储坐标再怎样还原吧:
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
public void mouseReleased(MouseEvent e) {
int x2 = e.getX();
int y2 = e.getY();
if(command.equals("line")){
//画一条直线
db.g.drawLine(x1,y1,x2,y2);
array_line[4*i_line] = x1;
array_line[4*i_line+1] = y1;
array_line[4*i_line+2] = x2;
array_line[4*i_line+3] = y2;
i_line++;
}
这样我们就把每一条直线的坐标按照四个四个一组给存入到array_line这个数组中。
那么再重绘方法中是怎么写呢?
dpaper = new DrawPanel(dListener){public void paint(Graphics g){
super.paint(g);
for(int i = 0;i<DrawListener.array_line.length/4;i++){
g.drawLine(DrawListener.array_line[4*i], DrawListener.array_line[4*i+1], DrawListener.array_line[4*i+2], DrawListener.array_line[4*i+3]);
}
};
其中dpaper是画布的那块面板,这里我们使用了一个匿名内部类,其中super.paint(g);这一语句的作用是调用父类的paint方法,用来绘制窗体。 使用for循环,4个4个一组来获取array_line中的数据并用之来绘制直线就完成了重绘的操作。
很显然使用一维数组来弄重绘真的十分麻烦不方便。接下来就是用二维数组来进行重绘的操作
二维数组的重绘
二维数组的重绘思想呢,大体上就是因为我们的计算机屏幕都是由一个个小的像素点所组成,画图板中间的那块画布也是由行多少个、竖多少个像素点的那样一个点阵所组成,所以设想一下如果我们利用一个二维数组讲每一个像素点的颜色存储起来,重绘的时候再把像素点的颜色还原回去,是不是也完成了重绘的功能呢?
接下来就来试一试吧:
这里需要使用之前没有用过的一个类Robot。他里面有一个方法:createScreenCapture。他的作用是用来截取屏幕上一部分图片。所以我们只要把画图板画布的部分使用这个方法截图下来,在一个一个点来扫面并将像素点的颜色数据存入一个二维数组就可以了:
public void getScrean(){
point1 = DrawBoard.dpaper.getLocationOnScreen();
Rectangle rect = new Rectangle((int) point1.getX(), (int) point1.getY(),DrawBoard.dpaper.getWidth(), DrawBoard.dpaper.getHeight());
BufferedImage image = robot.createScreenCapture(rect);
for(int i=0;i<image.getWidth();i++){
for(int j=0;j<image.getHeight();j++){
//将对应坐标点颜色值取出存入到二维数组中。
DrawBoard.array_paint[i][j] = image.getRGB(i, j);
}
}
}
其中有一个方法getLocationOnScreen。他的作用是获取画布的左上角坐标,之后再建立一个举行封装类用来作为createScreenCapture的参数,这样就把画布部分给用图片来保存下来了。
接下来在重写paint方法的时候只要一个个的将点颜色还原就好啦:
paper = new DrawPanel(dListener){
public void paint(Graphics g){
super.paint(g);
for(int i=0;i<array_paint.length;i++){
for(int j=0;j<array_paint[i].length;j++){
Color color = new Color(array_paint[i][j]);
g.setColor(color);
g.drawLine(i, j, i, j);
}
}
}
};
这样二维数组的重绘就完成了。与一维数组的重绘相比较很显然这个可以说比那种方法要强上10086条街……
画图板画布重绘又出了新方法啦:队列重绘以及图片重绘。
先来说下队列重绘:
在我们熟悉使用自定义队列之后,就可以发现自定义队列虽然说白了也就是一维数组,但他却具有一维数组很多不能比的优点。首先,我们定义数组的时候就要把数组的长度给设置好,并且在之后的操作中无法再改变数组的长度,因为java是无法操作系统内存的。队列则不同,他可以多次添加或者删除队列中的元素数据。数组还有一个缺点那就是定义了之后就只能存储一种数据类型的数据。然而队列只要我们使用泛型,就可以解决这个问题了。
那么现在我们就使用队列来对画图板进行重绘的操作。先来了解一下大题思路:我们每次在画板上画的图形,无论是直线矩形或者是铅笔喷漆,都可以说是一个个的对象,那么我们就可以使用队列来把这些对象都存储起来,然后在重绘方法中从头遍历队列中的元素再把他们给重新画到画布上,这样就完成了队列的重绘。在做之前,我们先要有一些准备:
1.首先自然而然要有一个自定义队列:
public class DuiLie {
Object [] list = new Object[0];
/*
* 向队列中加入元素
*/
public void add(Object m){
//创建一个新的数组,长度为原数组长度+1
Object [] newlist = new Object[list.length+1];
//将原数组中的元素存入新的数组当中
System.arraycopy(list, 0, newlist, 0, list.length);
newlist[list.length] = m;
list = newlist;
}
/*
* 获取队列长度
*/
public int getSize(){
return list.length;
}
/*
* 得到某一索引位置上的元素的方法
*/
public Object getItem(int index){
return list[index];
}
}
因为我们使用队列重绘只需要向队列中加入图形的对象,然后在遍历的时候需要知道队列的长度以及获得每一个位置的数据内容,所以在这个自定义队列中就这些了这三个方法。~
2.我们要给那些图形创建类
我们要把那些图形当成对象存储起来,所以就要创建一个图形类,然后不同的图形呢,只需要继承这个类就可以了。
import java.awt.Color;
import java.awt.Graphics;
public abstract class Shape {
/*
*定义属性
*/
public int x1,x2,y1,y2;
public Color color;
/*
* 重载构造方法
*/
public Shape(int x1,int y1,int x2,int y2,Color color){
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.color = color;
}
public abstract void draw(Graphics g);
}
这是定义的一个图形类,其中包含了五种属性,分别是我们在画图时获取的始末点的xy坐标以及画图时所选的颜色。
接下来就只拿直线和矩形这两个为例子来看看每个不同工具绘制图案的图形类怎么创建吧
import java.awt.Color;
import java.awt.Graphics;
public class Line extends Shape{
public Line(int x1, int y1, int x2, int y2, Color color) {
super(x1, y1, x2, y2, color);
}
public void draw(Graphics g) {
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
}
}
import java.awt.Color;
import java.awt.Graphics;
public class Rect extends Shape{
public Rect(int x1, int y1, int x2, int y2, Color color) {
super(x1, y1, x2, y2, color);
}
public void draw(Graphics g) {
g.setColor(color);
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
}
这两个类就是分别用来存储我们画直线和矩形时所画的图形的类。下面只要在监听器里面修改下就可以把这些图形存储起来:
if(command.equals("line")){
//画一条直线
shape = new Line(x1,y1,x2,y2,col);
}
else if(command.equals("rect")){
//画一个矩形
shape = new Rect(x1,y1,x2,y2,col);
}
shape.draw(db.g);
list.add(shape);
这样就是在我们画出图形的同时,又把那些图形存到shape中,并且添加到我们事先定义好的list队列中。
这些准备工作都做好了,接下来就是据图的重绘操作,也很简单:
dpaper = new DrawPanel(dListener){
public void paint(Graphics g){
super.paint(g);
for(int i=0;i<DrawListener.list.getSize();i++){
//把图形对象取出来,画图
((Shape)DrawListener.list.getItem(i)).draw(g);
}
}
};
只要在这里重写一下重绘方法,使用循环遍历队列中的元素,并将每一个元素画出就可以啦。
这样队列重绘就完成了。
除了这个还有一中更为简单的重绘的方法:图片重绘。
这种方法与我们之前使用的二维数组的重绘很相似,二维数组的重绘是通过把我们画布给作为一张图片截取下来,之后把那张图片每一个像素的颜色都存储起来,并在重绘的时候一个个绘制上去来完成的,而图片重绘则是直接把整个图片都重新贴上去一样。这里就只要用到一个方法:
drawImage(Image img, int x, int y, ImageObserver observer);
这个方法是Graphics中的一个,他就是在指定位置绘制一张图片。所以我们使用图片重绘只需把之前用二维数组做重绘所截取的图片使用这个方法在重绘的时候贴到画布上就好了。但这里有一个需要并且容易犯错误的地方:就是我们重绘这张图片的xy坐标是什么。就是那个函数中的第二和第三个参数。看API文档很显然可以知道xy指的是:图像的左上角位于该图形上下文坐标空间的 (x, y)。所以我们在画布上进行重绘,所以所用的xy坐标都只要为0就行了。这里不要误以为是我们的画图板在屏幕上的坐标,那样就会出先重绘时候图片位置不对的情况的。
这样~~我们所画的各种图案~只要不关闭窗口就不会再随着最大化或者最小化而消失啦!
这样我所知道的4种重绘方法就都已经在这里了,再对这些方法进行一个小小的总结与比较呢:~
显然,第一种一维数组重绘是最不好的,我觉得可以这么说,因为如果我们把数组定义的过小,那么绘制图片较多的时候后面绘制的就存不下了,如果定义的较大则是对内存的一种浪费。
二维数组重绘,相比以为数组确实有优点,但是这个重绘是一个一个点绘制,执行速度上肯定不会很快。
队列的重绘就完全避免的一维数组重绘的缺点,但是我觉得那样每一个图形建一个类也好麻烦的。。。
。。所以呢。我个人认为最好最简单的还是图片重绘。。嘿。
关于重绘的总结就这些吧。希望可以给看这篇文章的亲们点点帮助~~
分享到:
相关推荐
【小小画图板开发——JAVA课程设计报告】 本报告详细阐述了一款基于Java开发的简易画图板程序,旨在提供类似Windows操作系统自带的画图工具的功能。通过参与这个项目,学生能够将已学的Java编程知识付诸实践,增强...
### 基于VC++MFC程序设计——简易画图板 #### 概述 本文档将详细介绍如何利用VC++中的MFC(Microsoft Foundation Classes)框架来开发一款简易的画图板应用程序。该画图板的主要功能包括但不限于图形的绘制、线型...
本项目名为"C++程序——画图板",其核心是利用C++来实现一个简单的画图工具,让用户可以在界面上绘制图形。下面我们将深入探讨这个项目的相关知识点。 首先,我们要理解C++中的图形用户界面编程。在C++中,可以使用...
画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码画图板 代码...
在本次的“MFC画图板——图形学课程设计”项目中,我们主要涉及了三个核心领域:MFC(Microsoft Foundation Classes)、VC++(Visual C++)编程以及图形学基础知识。下面将对这些知识点进行详细阐述。 首先,MFC是...
这篇实验报告讲述了如何使用Java语言中的SWT(Standard Widget Toolkit)和Graphics2D类来实现一个简单的二维画图板。...通过不断地完善和扩展,这样的画图板可以成为一个功能完善的图形编辑软件,满足更多用户的需求。
在本文中,我们将深入探讨BMP格式的解析与保存,并结合画图板的重绘功能来讲解这一主题。 首先,我们需要理解BMP文件的结构。BMP文件分为两部分:文件头和图像数据。文件头包含文件信息,如文件大小、图像宽度、...
《Windows画图板:探索动态画图的魅力》 Windows画图板,作为一款简单易用的图形编辑软件,是微软操作系统内置的一个基础工具,尤其适合初学者和儿童进行简单的绘图活动。它提供了丰富的基本画图功能,让用户能够...
【压缩包子文件的文件名称列表】:张飞翔——画图板 这个文件名表明这个压缩包是由一个叫“张飞翔”的人创建或整理的,他可能是这个画图板软件的开发者或者贡献者。这个文件很可能是画图板的源代码、编译后的可执行...
在Java编程语言中,实现一个简单的Windows画图板是一个经典的练习,它可以帮助初学者更好地理解图形用户界面(GUI)的设计以及事件处理机制。这个项目通常会涉及到Java的Swing库,这是一个用于创建桌面应用程序的GUI...
在Java学习过程中,创建一个简单的画图板是一个经典的练习项目,它可以帮助我们深入理解图形用户界面(GUI)的构建和事件处理机制。本篇小结将聚焦于如何使用Java实现一个基本的画图板,同时提供相关的源码分析。 1...
Java 画图板程序设计与实现 Java 画图板是使用 Java 语言编写的图形绘制程序,提供了基本的绘图功能,如画笔、直线、椭圆、矩形等,用户可以使用该程序绘制简单的图形。下面我们将对 Java 画图板程序进行详细的分析...
QT画图板是一个基于Qt库开发的图形用户界面应用程序,主要功能是提供一个交互式的画布,用户可以在上面进行绘图操作。对于初学者来说,QT画图板是一个极好的学习资源,它展示了Qt库在图形绘制和用户交互方面的强大...
在这个“关于画图的软件——亿图图示PJ版”的压缩包中,包含的是亿图图示9.2版本,这是该软件的一个稳定版本,确保用户可以流畅地进行图形设计工作。 1. **亿图图示的核心特性** - **模板丰富**:亿图图示提供了...
win10画图板下载,解压点击即可用 win10画图板下载,解压点击即可用 win10画图板下载,解压点击即可用 win10画图板下载,解压点击即可用 win10画图板下载,解压点击即可用 win10画图板下载,解压点击即可用 win10...
通过重写paintComponent方法,可以确保每次窗口重绘时都能正确显示当前的绘图状态。 对于保存和加载功能,Java提供了文件I/O流类,如FileInputStream和FileOutputStream,用于读写文件。图像数据可以被序列化为二...
paintEvent是一个在QWidget中定义的事件处理函数,当组件需要重绘时,它会自动被调用。在绘图应用中,这个函数通常会被用来绘制图像。 #### QImage与QPainter QImage是一个图像表示类,用于处理图像数据。QPainter...
这个"基于qt实现的画图板"项目提供了一个基础的图形用户界面(GUI)应用,让用户能够进行基本的绘画操作,比如选择画笔、填充颜色、打开和保存图像。以下是关于这个项目的一些关键知识点和相关技术的详细解释: 1. ...
《VC++实现的简易画图板程序解析》 在计算机编程领域,开发一款类似Windows画图板的小程序是一项常见的实践项目,它可以帮助初学者更好地理解图形用户界面(GUI)编程和基本的图像处理技术。本篇文章将深入探讨一个...