将画图板界面上的图像信息保存到本地
想必很多人的java入门级项目就是做一个画图板吧,那么,当你在画图板上绘制一些图形(如直线、矩形、多边形等)或者进行图像处理(如马赛克,灰度,边缘提取,高斯模糊等)后,如何将画图板上的图像信息保存到本地呢?这个问题困扰我好久,后来有幸在CSDN见到了大佬BlueSky_USC的文章画图板图形保存才彻底搞懂了,接下来我讲一下原理。
其实原理类似之前做过的重绘效果,跟重绘一样需要建立一个“存储容器”,而且重绘和图像本地保存可以共用这个容器,这个容器可以是数组(Shape []),也可以是列表(ArrayList《shape》此处应该是尖括号<>),只需要每次绘制后,将信息存储进入数组或列表,然后再创建一个bufferedImage对象,将容器中的数据遍历出来绘制到缓存图片中,然后调用ImageIO.write写入本地即可。
再说一句,我觉得BlueSky_USC的程序中有一个值得学习的地方就是创建了一个Shape抽象父类,然后再创建Line、Rect、Oval等图形类,继承抽象父类,重写抽象父类中的Draw方法,大家可以去想一下这样写的好处。
话不多说,开始分析代码:
首先,我把容器创建在了窗体类DrawFrame中,因为重绘的时候需要重写paint方法,而paint方法就是在窗体类DrawFrame中重写的(需要继承JFrame才能重写),这样会方便些。
ArrayList<Shape> list = new ArrayList<Shape>(); //容器
当然,list的存储应该是在绘制过程中,那我们实现绘制的代码是放在Drawmouse监听器类中的,所以此时需要在Drawmouse监听器类中创建一个list变量,然后写一个传递list的方法,将窗体类中的容器传递到监听器类中,如下:
ArrayList<Shape> list;
public void setList(ArrayList<Shape> list){
this.list = list;
}
窗体类中需要做以下操作:
Drawmouse mouse = new Drawmouse();
mouse.setList(list);
这样就实现传递过程了,感觉讲的有点啰嗦
接下来,就是往list中存数据,跟重绘一样,每一个绘制命令结束后都需要存储,如下:
public void mousePressed(MouseEvent e) {
x1=e.getX();
y1=e.getY();
}
public void mouseReleased(MouseEvent e) {
x2=e.getX();
y2=e.getY();
if(type.equals("直线")){
Line line = new Line(x1,y1,x2,y2,col); //这里是我自己写的Line类的构造方法,创建对象+传值操作二合一
line.Draw(gr); //Line类中的画直线方法
list.add(line); //记得存到容器里
}
if(type.equals("矩形")){
Rect rect = new Rect(x1,y1,x2,y2,col);//这里是我自己写的Rect类的构造方法,创建对象+传值操作二合一
rect.Draw(gr);//Rect类中的画矩形方法
list.add(rect);//记得存到容器里
}
记住一个原则,只要是有绘制命令,后面都要记得存容器,图像处理(如马赛克,灰度,边缘提取,高斯模糊等)也要存。
好了,存完之后就可以画了,继续,在监听器类中自己写一个保存方法:
public void mouseClicked(MouseEvent e) {
if("保存".equals(type)){
saveFile();
}
}
public void saveFile(){
JFileChooser chooser = new JFileChooser(); //这几步是调出一个文件保存弹窗
chooser.showSaveDialog(null);
File file = chooser.getSelectedFile();
if(file == null){
JOptionPane.showMessageDialog(null, "没有选择文件");
}else{
try {
BufferedImage buffi = new BufferedImage(800,700,1); //800和700是根据窗体尺寸设定的,1代表TYPE_INT_RGB
Graphics2D g2d = (Graphics2D)buffi.getGraphics(); //获取缓存图片的画笔
g2d.setColor(Color.WHITE); //保存图片的背景色,如果不设置就是黑色的
g2d.fillRect(0, 0, 800, 700);
for(int i = 0;i<list.size();i++){ //遍历list列表,将存储的所有图像信息画在一张缓存图片上
list.get(i).Draw(g2d);
}
ImageIO.write(buffi,"png",file); //以png格式写入文件,file是文件保存弹窗获取的文件信息,意思是将图片保存在这个文件内
JOptionPane.showMessageDialog(null, "保存成功!");
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
最终效果: