上一篇博文已经具体的构建了画图板的整个框架 这里就具体的说明一下功能的实现问题
一、功能实现
1.简单的画图形
2.重绘:窗体最小化之后 打开窗体 画面不消失
3.保存文件: 把绘制出来的图片放在硬盘里
二、难点分析
三、错误点集合
1.简单的画图形
画图形分为三步:
第一步:取画布
// 给他drawpanel获取画布
java.awt.Graphics g = drawpanel.getGraphics();
第二步:取颜色 取图形
g.setColor(Color.LIGHT_GRAY);
第三步:绘制图形
g.drawLine(x1, y1, x2, y2);
2.重绘:窗体最小化之后 打开窗体 画面不消失
介绍两种方法:
第一种:每个画出的图形用队列保存 重绘时只需遍历队列重画一下
建立队列 每次取到的sh都加到队列里
// 定义一个队列用来存放形状对象~
MyQueue<Shape> shapes;
//建立一个Shape类型的对象把他设置为null
Shape sh = null;
//将图形加入队列
shapes.add(sh);
//把图形画出来
sh.draw(g);
新建一个MyPanel类因为画布是在drawpanel上面取的
遍历形状队列 绘制出图形
class MyPanel extends JPanel {
/**
* 重写JPanel中用来绘制窗体的方法
*/
public void paint(Graphics g) {
// 调用父类的方法来正确的绘制窗体
super.paint(g);
System.out.println("绘制了");
// 遍历形状队列
for (int i = 0; i < shapes.size(); i++) {
// 取出形状
Shape sh = shapes.get(i);
// 绘制
sh.draw(g);
}
}
}
第二种方法:捕捉屏幕方法
因为drawpanel是由屏幕上的像素点组成的
有不同的颜色是因为像素点各点存的颜色不一样,屏幕可以抽象看做一个二维数组
所以只需要取到二维数组里每点的颜色即可
核心是
// 创建Rectangle对象
Rectangle rec = new Rectangle(point, drawDim);
// 捕捉drawpanel上的像素图像
BufferedImage bimg = rb.createScreenCapture(rec);
// 建立一个robot对象
try {
Robot rb = new Robot();
// 获取drawpanel左上角的点~
Point point = drawpanel.getLocationOnScreen();
// 获取drawpanel的dimension
int width = drawpanel.getWidth();
int height = drawpanel.getHeight();
java.awt.Dimension drawDim = new java.awt.Dimension(width, height);
// 创建Rectangle对象
Rectangle rec = new Rectangle(point, drawDim);
// 捕捉drawpanel上的像素图像
BufferedImage bimg = rb.createScreenCapture(rec);
// 现在要找图像上的像素点用一个二维数组来储存每个点的像素
// 为存放屏幕上各点的颜色设置一个二维数组array
Array.pointArray = new int[height][width];
for (int i = 0; i < Array.pointArray.length; i++)
for (int j = 0; j < Array.pointArray[i].length; j++) {
// x是像素的x坐标 j是列 x = 1 为第一列~getRGB传入的应该是x y
Array.pointArray[i][j] = bimg.getRGB(j, i);
}
3.保存文件: 把绘制出来的图片放在硬盘里
首先 在frame上设置按钮 通过监听器跟文件io流连接
//加菜单项
final javax.swing.JMenuItem item1 = new javax.swing.JMenuItem("保存");
final javax.swing.JMenuItem item2 = new javax.swing.JMenuItem("打开");
//加动作命令
item1.setActionCommand("save");
item2.setActionCommand("open");
//建立匿名内部类 并
ActionListener alis = new ActionListener(){
public void actionPerformed(ActionEvent e) {
//给item1和item2设置命令
String command1 = item1.getActionCommand();
String command2 = item2.getActionCommand();
if(command1.equals("save")){
//把图片保存成文件
FileUtil.saveFile("G:\\蓝杰\\first.bmp");
}
if(command2.equals("open")){
//把ispaint设置为true
DrawListener.isPaint = true;
//把文件从硬盘读取出来
int[][] readData =FileUtil.readFile("G:\\蓝杰\\first.bmp");
DrawListener.Point_Array = readData;
//DrawListener.POINT_ARRAY = readData;
System.out.println(readData);
// 刷新drawPanel
drawpanel.updateUI();
}else{
System.out.println("出错了!!");
}
}
};
item1.addActionListener(alis);
item2.addActionListener(alis);
然后:创建保存文件的方法
/**
* 保存文件的方法
* @param path 要保存到的路径
*/
public static void saveFile(String path){
try{
//创建文件输出流
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
//把他包装成数据流
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);
//首先写入图片的高度和宽度
dos.writeInt(DrawListener.Point_Array.length);
dos.writeInt(DrawListener.Point_Array[0].length);
//遍历颜色数组把颜色点都写入文件
for(int i =0;i<DrawListener.Point_Array.length;i++)
for(int j = 0;j<DrawListener.Point_Array[i].length;i++){
//把颜色数组的内容写入文件
dos.writeInt(DrawListener.Point_Array[i][j]);
}
//把数据流强制输出 文件流关闭
dos.flush();
fos.close();
}catch(Exception e){
e.printStackTrace();
}
}
创建读取文件的方法
/**
* 读文件 从硬盘到内存
* @param path 要读入的文件路径
*/
public static int[][] readFile(String path){
try{
//创建文件输入流
java.io.FileInputStream fis = new java.io.FileInputStream(path);
//把他包装成数据流
java.io.DataInputStream dis = new java.io.DataInputStream(fis);
//先读出数组的宽和高 放入新的二维数组里~
int height = dis.readInt();
int width = dis.readInt();
//根据宽和高创建一个新的二维数组
int[][] array = new int[height][width];
//读取颜色把颜色放在新的二维数组里
for(int i=0;i<height;i++)
for(int j = 0;j<width;j++){
array[i][j] = dis.readInt();
}
//只需要关闭输入流即可
fis.close();
return array;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
二、难点分析
1.捕捉屏幕方法中取到二维数组里每点的颜色
这里用了Color()的一种没用过的构造方法
就是 int值表示一个颜色 因为我们要把颜色放进二维数组
所以二维数组里的颜色只能有一个值 就是int
首先从捕捉drawpanel上的像素图像这个函数开始
BufferedImage bimg = rb.createScreenCapture(rec);
需要一个Rectangle
创立Rectangle需要point和drawDim
所以就构造point和drawDim
BufferedImage有一个getRGB的方法 正好可以把它的int值放进颜色数组里
这样就实现了捕捉屏幕(详细代码见 “二、重绘”)
2.关于记录颜色数组是放在接口还是类中的问题
开始时我把 Point_Array放入接口中 但接口中的数组大小不能发生改变
而实际操作中
在读取文件的函数里 获取的数组高度和宽度是放在新建的数组里
//根据宽和高创建一个新的二维数组
int[][] array = new int[height][width];
//读取颜色把颜色放在新的二维数组里
for(int i=0;i<height;i++)
for(int j = 0;j<width;j++){
array[i][j] = dis.readInt();
}
所以在listener里面要把新数组赋给Point_Array 结果出现了问题
后来 就把Point_Array放进了drawlistener里就实现了
三、错误点集合
1. 这个readfile函数里 return有点小技巧
在try里面 return 这个二维数组 在外面 return null
说明 只有try了 才return
2.ispaint的问题
出现整个drawpanel全部是黑色的情况
错点分析:
画布的设置颜色的方法传入的是颜色的一个int 值
g.setColor(new Color(POINT_ARRAY[i][j]));
这句代码 当画面上还没有绘制形状的时候POINT_ARRAY[i][j]都是零 而零表示黑色
所以一开始整个屏幕都是黑色
所以我们在listener里设置了一个布尔型的变量ispaint来判断他是否已经有内容
public static boolean isPaint = false;
在mouserelease()函数的最后 当存入数据到数组中时
分享到:
相关推荐
在本文中,我们将深入探讨BMP格式的解析与保存,并结合画图板的重绘功能来讲解这一主题。 首先,我们需要理解BMP文件的结构。BMP文件分为两部分:文件头和图像数据。文件头包含文件信息,如文件大小、图像宽度、...
9. **保存与加载**: 可能还实现了将画布内容保存到文件(如BMP或PNG格式)以及从文件加载的功能。这涉及到`Bitmap`类的使用,以及文件I/O操作。 10. **代码组织与设计模式**: 良好的源码结构可能包括多个类,每个类...
通过重写paintComponent方法,可以确保每次窗口重绘时都能正确显示当前的绘图状态。 对于保存和加载功能,Java提供了文件I/O流类,如FileInputStream和FileOutputStream,用于读写文件。图像数据可以被序列化为二...
2. 绘图处理:在OnPaint()消息处理函数中,当窗口需要重绘时,会调用BeginPaint()和EndPaint()来获取CDC对象,并在其中进行绘图操作。 3. 用户交互:程序需要响应用户的鼠标和键盘事件,如WM_LBUTTONDOWN、WM_...
"简单画图板的设计"是一个关于创建一个基本图形编辑器的话题,主要涉及到计算机图形学、用户界面设计以及可能的编程实现。在这个项目中,我们可能会遇到以下关键知识点: 1. **计算机图形学基础**:画图板应用的...
这可能是通过设置一个特定的颜色(如背景色)和不透明度,然后在指定区域内重绘,以达到擦除效果。 5. **颜色选择**:用户可以改变画笔颜色,这需要实现颜色选择器,可能是一个颜色对话框,用户选择颜色后,将所选...
这个函数会在视图需要重绘时被调用,我们可以在这里使用GDI (Graphics Device Interface) 来绘制图形。GDI 提供了一系列的函数,如MoveTo、LineTo、Rectangle、Ellipse 和Polyline,它们分别用于绘制线条、矩形、...
你需要定义消息映射来处理特定的消息,如WM_PAINT消息用于窗口重绘,WM_LBUTTONDOWN和WM_LBUTTONUP用于处理鼠标点击。 7. **文件I/O**:为了实现打开和保存BMP文件的功能,你需要使用CFile类或者更高级的fstream来...
4. **重绘机制**:为了保证画图板的实时性,开发者可能利用了JAVA的重绘机制,如`repaint()`方法,当画布上的内容发生变化时,会自动调用该方法进行更新,确保用户能即时看到画图的效果。 5. **图像处理**:除了...
5. **图形文件重绘与保存:** - 为了支持图形文件的保存,可以使用`CDC`类的`SaveDC`方法来保存绘图状态。 - 要实现图形文件的重绘,可以通过读取保存的状态并再次调用绘图函数来实现。 - 文件保存格式可以选择为...
5. **OnPaint消息**:当窗口需要重绘时,Windows会发送WM_PAINT消息。我们需要重载CWnd的OnPaint成员函数,来实现自定义的绘图逻辑。 6. **CPaintDC类**:为了在窗口上绘图,我们将使用CPaintDC类,它是设备上下文...
在C#编程环境中,开发一个简单的画图板是一项常见的练习,可以帮助初学者更好地理解图形用户界面(GUI)的创建和事件处理。这个源码提供了一个基础的画图应用,允许用户绘制矩形、曲线和椭圆,并且可以选择系统提供...
功能主要有: 手绘线、简单图形、文字输入、图块拖放、重复撤销、画面缩放、打开保存图片文件,另外为了直接从数据库或者XML中存取图片,另外还提供了从Base64编码存取图片的接口,其他还实现了和画图板同样效果的...
6. **擦除与重绘**: 为了实现擦除功能,可以创建一个白色的Pen,然后在擦除区域调用DrawRectangle方法。但请注意,Windows Forms的Graphics对象通常不会自动清除画布,所以可能需要在Paint事件中实现自己的清除...
【画图板源代码】是计算机编程领域中的一个项目,主要涉及图形用户界面(GUI)设计,特别是使用C#编程语言实现的一个简单的绘图应用程序。这个项目的核心目标是为用户提供一个平台,他们可以在这个平台上自由地绘制...
7. **性能优化**:由于连续的`MOUSE_MOVE`事件可能导致频繁的屏幕重绘,可能需要引入缓冲机制,比如定时器控制绘图频率,或者使用中间画布存储绘制过程,然后一次性更新主画布以减少刷新次数。 这个"Flash交互画图...
从压缩包文件的名称“画图板可保存重绘”来看,该画图板特别强调了保存和重绘的功能。这意味着它可能包含了一个高效的数据结构用于存储用户的绘图操作序列,以便在需要时能精确地恢复。这可能涉及到序列化和反序列化...
在按钮的点击事件中,可以简单地重绘面板以恢复到初始状态,或者创建一个新的位图并在每次绘图时覆盖到原来的位图上,以实现橡皮擦功能。 5. **保存与加载**: 实现保存和加载功能,你可以将画图板的内容保存为...
在Android平台上,开发一个画图板应用是一项有趣的挑战,它涉及到图形用户界面(GUI)设计、触摸事件处理以及图像操作等多个技术领域。"android画图板"是一个典型的例子,它为用户提供了一个可以自由绘画、擦除、...
在VC++环境中创建一个画图板涉及到许多关键知识点,包括: 1. **MFC库**:VC++通常使用Microsoft Foundation Classes (MFC) 库,这是一个C++类库,用于构建Windows应用程序。MFC提供了对Windows API的封装,简化了...