Java编写画图板程序细节-保存已画图形
没有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编写画图板程序细节-保存已画图形的更多相关文章
- 使用JAVA编写电话薄程序,具备添加,查找,删除等功能
//该程序需要连接数据库.根据word文档要求所有功能均已实现.//大部分方法基本差不多,//在查询修改的时候能输出 最大ID号 和最小ID号,并且可以对输入的ID号进行判断是否存在(具体方法请查看 ...
- Java编写时钟 Applet 程序
简单分析: package clockApplet; import java.applet.Applet; import java.awt.Color; import java.awt.Graphic ...
- java编写的2048程序
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util ...
- Java 编写小程序,下载指定网页上的所有图片
使用Java编写一个小程序,可以根据指定的网页地址,下载网页中的所有图片:使用到网络编程.线程池.IO和UUID的技术.具体代码如下: import java.io.File; import java ...
- 很值得学习的java 画图板源码
很值得学习的java 画图板源码下载地址:http://download.csdn.net/source/2371150 package minidrawpad; import java.awt.*; ...
- Java版简易画图板的实现
Windows的画图板相信很多人都用过,这次我们就来讲讲Java版本的简易画板的实现. 基本的思路是这样的:画板实现大致分三部分:一是画板界面的实现,二是画板的监听以及画图的实现,三是画板的重绘.(文 ...
- JAVA 画图板实现(基本画图功能+界面UI)一、界面实现
/*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 1978702969@qq.com*/ 这段时间在学JAVA的swing界面开发,试着做了个画图板.实现了直线.曲线.喷枪.矩形.圆形.文字 ...
- Java 从零开始实现一个画图板、以及图像处理功能,代码可复现
Java 从零开始实现一个画图板.以及图像处理功能,代码可复现 这是一个学习分享博客,带你从零开始实现一个画图板.图像处理的小项目,为了降低阅读难度,本博客将画图板的一步步迭代优化过程展示给读者,篇幅 ...
- JAVA 画图板实现(基本画图功能+界面UI)二、功能实现及重绘实现
上篇博客中介绍了界面的实现方法,在这篇博客中将对每个按钮的功能的实现进行讲解并介绍重绘 首先肯定要添加事件监听机制了,那么问题来了,事件源对象是谁?需要添加什么方法?事件接口是什么? 1.我们需要点击 ...
随机推荐
- Css选择器(上) 让样式无孔不入
css选择器 一个可以选择样式的工具, 这里适用于无论是内部代码还是外部引用 abc.css 这类型的文件. 基本选择器*{ } 就是一个简单的*, 代表应用于全部. 不适合于个性 ...
- swiper动态改变滑动内容
假设当前显示的是1,往左滑动一个递减1,往右滑动一个递增1 body下面添加如下代码 <div class="swiper-container temp"> <d ...
- <Android 应用 之路> MPAndroidChart~ScatterChart
简介 MPAndroidChart是PhilJay大神给Android开发者带来的福利.MPAndroidChart是一个功能强大并且使用灵活的图表开源库,支持Android和IOS两种,这里我们暂时 ...
- apk 反编译 - 最新版图文教程
apk 反编译 - 最新版图文教程 结合网上众多教程,整理一篇自己操作的,工具都是目前最新版 apk 反编译也就是将打包后的 apk 反编译为资源文件(图片).layout.样式.相关的实现代码等.( ...
- Oralce 序列
序列: 是oacle提供的用于产生一系列唯一数字的数据库对象. l 自动提供唯一的数值 l 共享对象 l 主要用于提供主键值 l 将序列值装入内存可以提高访问效率 创建序列: 1. 要有创建 ...
- sql查询学习和实践点滴积累
https://blog.rjmetrics.com/2008/10/28/correlated-subqueries-in-mysql/ http://www.mysqltutorial.org/m ...
- chchc
---恢复内容开始--- 51CTO博客-原创IT文章分享平台 Logo 首页 文章 专家 专家博客 博客之星 推荐博客 我的博客 网站导航 学院 博客 下载 家园 论坛 CTO训练营 WOT 51C ...
- Http扫盲
https://www.kancloud.cn/kancloud/tealeaf-http/43832
- 无法打开项目文件“Web.csproj” 此安装不支持该项目类型
今天把另外一个项目拷贝到我自己的机器上运行,发现突然打不开webapplication项目了,提示:无法打开项目文件“Web.csproj” 此安装不支持该项目类型.,就是那个网站,用度娘网上搜了一大 ...
- [BZOJ 1124][POI 2008] 枪战 Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 659 Solved: 259[Submit][Status ...