没有Java编写画图板程序细节-保存已画图形

 

一、为何我们要保存画图板上已画图形呢?

  有很多人会问,为什么我们一定要保存画图板上已经画好了的图形呢?原因很简单。当我们在画图板上画完自己想画的图形后,如果进行以下几个操作,就会发现几个降低用户体验感的问题,而这些问题就是由于没有保存已画图形造成的。

  首先第一种情况,如果你画完图形后,突然发现QQ或者微信来消息了,然后你一般会将画图板最小化然后去查收信息,当你再次回到画图板程序的时候你会惊奇的发现,你辛辛苦苦绘出的图片不翼而飞(哭了)。

最小化之前                       

     

最小化然后再次进入界面后

  第二种情况,当你发现画图板的大小不合适,画到一半想要调整画图板大小时,一旦你调整画板的大小,你又会惊奇的发现,画好的图形又不见了!

调整画图板大小之前                        

      

调整大小之后

  第三种情况,有时候你觉得画图板正好覆盖了一些你想看的内容,你接下来肯定会把画板界面往电脑屏幕边界拖从而来看你想看的被覆盖的内容,但是如果你拖过度了(把画板界拖到了屏幕外面了),那么恭喜你,图,又没了!!!

没有移动画图板界面之前

移动画图板界面到屏幕外

移动画图板界面然后拖回原处后

  怎么样?是不是感觉体验感极差,如果这要是别人设计出来的画图板,你会有用下去的兴趣吗?还在等什么,咱们一起来找到问题的根源来解决这个坑爹的设计吧!

二、为何会出现已画图形消失的情况呢?

  要想明白出现这个问题的根源呢,首先要明白一个原理:每当我们把将画图板最小化再打开时、拖动画图板到边缘再拉回来时或者是改变画图板大小时,都是画图板的Frame框架在不断调用它的paint方法的时候。其实这个很好理解,想想我们写的代码中有给Frame添加组件的部分,而这些组件包括框架本身是如何可视化让我们用户看见的呢?就是通过paint方法将这些组件“画”到了我们的电脑屏幕上才让我们看到了这些组件。那么当我们将画图板最小化,将画图板拖到边缘或者改变画图板大小的时候,都是画图板的可视化部分在改变的时候(最小化的时候画图板可视化部分全部消失,拖到边缘的时候画图板可视部分部分消失,改变大小的时候画图板可视部分大小改变)。既然画图板可视部分要改变了,就必须通过重新“画”一个新的面板上去才能实现状态的改变,这就是paint方法调用的原因。而Paint方法是一个java早已经定义好的一个方法,设计者并不知道我们用paint方法是来画什么图形的,设计者在设计之初只定义了用paint方法把这些组件画出来了,却并没有画我们自己创造的这些图形的这个部分。因此当程序自动调用paint方法时,就没有实现我们之前画的图形的可视化过程,只实现了框架组件的可视化过程,这就是为什么会出现已画图形消失的原因。

三、如何解决paint方法无法绘制用户已画图形呢?

  1、保存当前已经绘制了的图形

    ①用什么来保存我们已经绘制了的图形?

    试想我们绘制一个图形需要一些什么属性与方法呢?就拿直线来说,我们绘制一条直线首先需要知道这个直线的起始点与终止点,如果有设计需要的话还需要知道这条直线的颜色和粗细等等,当然还有一个最重要的属性,名字(例如“直线”),因为当我们绘制一个图形对象的时候我们要知道对象是哪个类型的图形,这样我们才能使用对应的方法来绘制这个类型的图形。既然一个图形通过它自己的属性和相应的方法能够绘制出相应的图形,那么我们不妨创建一个Shape类来实现保存的功能,将所有的图形有关信息保存到Shape对象中,再调用Shape对象中的绘制方法从而实现可视化图像的保存功能。

    具体代码如下:

 public class Shape {
private int x1,y1,x2,y2,x3,y3;
private String name;
private Color color; public Shape(String name,Color color,int x1, int y1,int x2,int y2,int x3,int y3){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.name = name;
this.color = color;
} public void drawshape(Graphics g){
switch(name){
case "直线":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
break;
case "三角形":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
g.drawLine(x1, y1, x3, y3);
g.drawLine(x2, y2, x3, y3);
break;
case "矩形":
g.setColor(color);
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
break;
} } }

    ②具体如何将这些图形保存到Shape对象中?

    由于我们的图形不止一个,所以我们需要创建一个对象数组,例如Shape[]Shapearray = new Shape;来保存不同的图形。然后在同时继承了鼠标监视器、动作监视 器、鼠标动作监视器的监视器类中来不断往这个对象数组里面添加元素。例如当我们画 直线的时候,我们首先点击“直线”按钮与“颜色”两个按钮,这个时候我们监视器就 已经通过name属性和color属性保存了相应的名字和颜色,然后当我们通过鼠标点击 移动释放后得到x1,y1,x2,y2四个坐标,这个时候我们的监视器就已经通过判断名字颜色 以及坐标位置实现了绘图功能,那么我们需要添加的步骤呢就只是在绘制完图形以后继 续创建一个Shape类型的对象(通过构建函数初始化属性),然后再把这个对象赋给对 象数组里面的一个元素就实现了一个直线对象的保存。其它类型的对象以此类推。

    具体代码如下:

 public class Drawlistener implements ActionListener,MouseListener,MouseMotionListener{

     private int x1,y1,x2,y2,x3,y3,i=1,j=1,count=1,number = 0;
private String name;
private Color color = Color.BLACK,color2;
private Graphics gr;
private JFrame frame;
private Shape[] shapearray = new Shape[1000000];
public Shape[] getshapearray(){
return shapearray;
}
public void setgraphics(Graphics gr1){
gr = gr1;
}
public void setcolor(Color color1){
color2 = color1;
} @Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if("".equals(e.getActionCommand())){
JButton botton = (JButton)e.getSource();
color = botton.getBackground();
gr.setColor(color);
}
else{
name = e.getActionCommand();
}
System.out.println(name);
} @Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
if("三角形".equals(name)){
x3 = e.getX();
y3 = e.getY();
gr.drawLine(x1, y1, x3, y3);
gr.drawLine(x2, y2, x3, y3);
i--;
Shape shape = new Shape(name,color,x1, y1, x2, y2, x3, y3);
shapearray[number++] = shape;
}
if("多边形".equals(name)){
count =e.getClickCount();
if(count==1){
x3 = e.getX();
y3 = e.getY();
gr.drawLine(x3, y3, x2, y2);
Shape shape = new Shape("直线",color,x3,y3,x2,y2,x3,y3);
shapearray[number++] = shape;
x2 = x3;
y2 = y3;
}
else{
gr.drawLine(x1, y1, x3, y3);
j--;
Shape shape = new Shape("直线",color,x1,y1,x3,y3,x3,y3);
shapearray[number++] = shape;
}
} } @Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if("直线".equals(name)||"矩形".equals(name)){
x1 = e.getX();
y1 = e.getY();
//System.out.println("x1 "+x1+"y1 "+y1);
}
if("三角形".equals(name)){
if(i == 1){
x1 = e.getX();
y1 = e.getY();
}
}
if("多边形".equals(name)&& j==1){
x1 = e.getX();
y1 = e.getY();
}
if("可拖动直线".equals(name)||"连续曲线".equals(name)){
x1 = e.getX();
y1 = e.getY();
}
} @Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
if("三角形".equals(name)){
if(i == 1){
x2 = e.getX();
y2 = e.getY();
gr.drawLine(x1, y1, x2, y2);
i++;
}
}
if("直线".equals(name)||"可拖动直线".equals(name)){
x2 = e.getX();
y2 = e.getY();
gr.drawLine(x1, y1, x2, y2);
//System.out.println("x1 "+ x1+"y1 "+y1+"x2 "+x2+"y2 "+y2);
Shape shape = new Shape("直线",color,x1,y1,x2, y2, x3, y3);
shapearray[number++] = shape; }
if("矩形".equals(name)){
x2 = e.getX();
y2 = e.getY();
gr.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
Shape shape = new Shape(name,color,x1,y1, x2, y2, x3, y3);
shapearray[number++] = shape; }
if("多边形".equals(name)&&j==1){
x2 = e.getX();
y2 = e.getY();
gr.drawLine(x1, y1, x2, y2);
Shape shape = new Shape("直线",color,x1,y1,x2,y2,x3,y3);
shapearray[number++] = shape;
j++; }
} @Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub } @Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub } @Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("我在努力拖动!");
if("可拖动直线".equals(name)){
gr.setColor(color2);
gr.drawLine(x1, y1, x3, y3);
x3 = e.getX();
y3 = e.getY();
gr.setColor(color);
gr.drawLine(x1, y1, x3, y3);
}
if("连续曲线".equals(name)){
x3 = e.getX();
y3 = e.getY();
gr.drawLine(x1, y1, x3, y3);
Shape shape = new Shape("直线",color,x1,y1,x3,y3,x3,y3);
shapearray[number++] = shape;
x1 = x3;
y1 = y3;
}
} @Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub } }

    ③保存了对象之后如何输出这些对象呢

    之前已经提到了我们原本写的图形之所以消失就是因为Java设计者在设计JFrame类的时候并没有在paint方法写我们之前画的那些图形的绘制,那么我们要做的就很简单了,就是重写JFrame的paint方法。而方法的重写是建立在继承关系上的,所以这个时候我们需要新创建一个类去继承JFrame类,这个类里面的内容和之前实现画图板的类基本一样,要做的只是把创建的JFrame对象删去,然后对所有对JFrame对象的属性或者方法的访问由“对象.”改为“this.”,因为你已经继承了JFrame类了,就不需要在类中在创建一个类的对象了。

紧接着要做的就是重写paint方法。具体操作呢:首先查看JFrame类的源代码,找到paint方法复制过来,然后在方法体里面写上 super.paint(g),因为我们重写方法还是要实现父类方法已有的功能,然后再在这个基础上写我们新创建的功能。

最后,将监视器保存的对象数组通过get方法传送到这个类里面来,通过for循环来将每一个对象绘制到面板上,这样就实现了对象的输出了。

    具体代码如下:

 public class Drawpanel extends JFrame{
Drawlistener drawlistener = new Drawlistener();
private Shape[] shapearray;
public void showpanel(){
this.setSize(1000,1000);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setLayout(new FlowLayout());
String[] shape = {"直线","矩形","三角形","多边形","连续曲线","可拖动直线"};
for(int i = 0; i < shape.length;i++){
JButton shapebotton = new JButton(shape[i]);
Dimension shapedimension = new Dimension(100,50);
shapebotton.setPreferredSize(shapedimension);
shapebotton.addActionListener(drawlistener);
this.add(shapebotton);
}
Color[] color = {Color.RED,Color.BLUE,Color.GREEN};
String[]colorname = {"红色","蓝色","绿色"};
for(int j = 0; j < color.length;j++){
JButton colorbotton = new JButton();
Dimension colordimension = new Dimension(100,50);
colorbotton.setPreferredSize(colordimension);
colorbotton.setBackground(color[j]);
colorbotton.addActionListener(drawlistener);
colorbotton.setToolTipText(colorname[j]);
this.add(colorbotton);
}
this.addMouseListener(drawlistener);
this.addMouseMotionListener(drawlistener);
this.setVisible(true);
Graphics gr = this.getGraphics();
drawlistener.setgraphics(gr);
drawlistener.setcolor(this.getBackground()); }
public void paint(Graphics g){
super.paint(g);
shapearray = drawlistener.getshapearray();
for(int i = 0; i < shapearray.length;i++)
{
if(shapearray[i] != null){
shapearray[i].drawshape(g);
}
else{
break;
} }
} public static void main(String[] args){
Drawpanel drawpanel = new Drawpanel();
drawpanel.showpanel();
} }

这样就解决了以上所说的问题了,上面的三段代码已经能够编写一个较为简单的画图板,希望能帮助到你们!

Java编写画图板程序细节-保存已画图形的更多相关文章

  1. 使用JAVA编写电话薄程序,具备添加,查找,删除等功能

    //该程序需要连接数据库.根据word文档要求所有功能均已实现.//大部分方法基本差不多,//在查询修改的时候能输出 最大ID号 和最小ID号,并且可以对输入的ID号进行判断是否存在(具体方法请查看 ...

  2. Java编写时钟 Applet 程序

    简单分析: package clockApplet; import java.applet.Applet; import java.awt.Color; import java.awt.Graphic ...

  3. java编写的2048程序

    import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util ...

  4. Java 编写小程序,下载指定网页上的所有图片

    使用Java编写一个小程序,可以根据指定的网页地址,下载网页中的所有图片:使用到网络编程.线程池.IO和UUID的技术.具体代码如下: import java.io.File; import java ...

  5. 很值得学习的java 画图板源码

    很值得学习的java 画图板源码下载地址:http://download.csdn.net/source/2371150 package minidrawpad; import java.awt.*; ...

  6. Java版简易画图板的实现

    Windows的画图板相信很多人都用过,这次我们就来讲讲Java版本的简易画板的实现. 基本的思路是这样的:画板实现大致分三部分:一是画板界面的实现,二是画板的监听以及画图的实现,三是画板的重绘.(文 ...

  7. JAVA 画图板实现(基本画图功能+界面UI)一、界面实现

    /*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 1978702969@qq.com*/ 这段时间在学JAVA的swing界面开发,试着做了个画图板.实现了直线.曲线.喷枪.矩形.圆形.文字 ...

  8. Java 从零开始实现一个画图板、以及图像处理功能,代码可复现

    Java 从零开始实现一个画图板.以及图像处理功能,代码可复现 这是一个学习分享博客,带你从零开始实现一个画图板.图像处理的小项目,为了降低阅读难度,本博客将画图板的一步步迭代优化过程展示给读者,篇幅 ...

  9. JAVA 画图板实现(基本画图功能+界面UI)二、功能实现及重绘实现

    上篇博客中介绍了界面的实现方法,在这篇博客中将对每个按钮的功能的实现进行讲解并介绍重绘 首先肯定要添加事件监听机制了,那么问题来了,事件源对象是谁?需要添加什么方法?事件接口是什么? 1.我们需要点击 ...

随机推荐

  1. ztree 获取当前选中节点的子节点集合

    功能:获取当前选中节点的子节点id集合. 步骤:1.获取当前节点 2.用ztree的方法transformToArray()获取当前选中节点(含选中节点)的子节点对象集合. 3.遍历集合,取出需要的值 ...

  2. c# copy类中值到另外一个对象中

    贴图: 调用:

  3. 解决servlet在web.xml中的路径跳转问题

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" ...

  4. Java 之集合框架 上(9)

    Java 中的集合框架 如果一个类中存在很多相同类型的属性. 例如:学生类 学生可以选课,因此存在很多课程类型的属性.但是每个学生选择的课程的种类和数量是不一样的. 如果将每一个课程类型的属性都列到课 ...

  5. MUI框架-11-MUI前端 +php后台接入百度文字识别API

    MUI框架-11-MUI前端 +php后台接入百度文字识别API 这里后台不止一种,Python,Java,PHP,Node,C++,C# 都可以 这里使用的是 php 来介绍,已经解决所有问题,因为 ...

  6. try catch 一点小记录

    这两天做了新的需求,做完之后 在测试环境下 完美通关.之后部署到了预发布环境,然而怎么尝试都不通过.刚开始看到 预发布的一个配置文件错了.发邮件改了下,但是依然流程跑不通.之后 一步步在测试环境看代码 ...

  7. Azure 虚拟机如何配置 AntiMalware

    本文仅演示通过 PowerShell 方式安装并配置 AntiMalware 的过程. 经典虚拟机          立即访问http://market.azure.cn 加载 Antimalware ...

  8. MySQL Database on Azure服务在中国正式商用

    基于由世纪互联运营的Windows Azure平台,MySQL Database on Azure服务助力中国用户实现数据库在云端的快速部署.推进用户的创新开发 2015年9月10日,北京——微软中国 ...

  9. js实现查找字符串出现最多的字符和次数

    代码如下: <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=" ...

  10. FTP上传(批处理)

    将以下内容保存为名为ftp_upload.txt的文件: open 192.168.11.199testw\adadminboc.123binaryput e:\wt.zipbye 在命令提示符下运行 ...