简单画图板总结
这个简单的画图板设计,主要有几个步骤:Java.swing中的组件,也就是窗体,然后是监听器,颜色的设置(包括图形的颜色和窗体的背景颜色)队列的使用,文件的保存和打开,图形的撤销和清零等一个步骤。
一. 画板界面
要设计一个画图板,首先需要窗体也就是画板界面(这里包括界面的一些属性)以及配套需要的窗体组件,如JButton, ButtonGroup,JradioButton.等等。。。
窗体的基本图形如下:
以上是一个简单的画板界面。
二. 绘制图形
所有图形都有共同点,它们的父类可以称之为图形,由于他们都有颜色和画的方法。所以,可以
定义一个图形的父类Shape。
父类定义好了,接下来就是想要画的各种子图形(只列出一种图形,其他的类似)的具体的实现类了。
三. 监听器
绘制的图形的方法有了,我们就可以开始画图了。画图的过程其实就是,当鼠标点击并拖动到释放时,就能够画出所需的图形来。所以就需要鼠标监听器,获得点击和释放时的坐标。这里为了简便画完之后就把它保存在自定义容器(下面在介绍下自定义队列)中。其次,在这里,又用到了动作事件,因为当点击一些按钮时,需要发生相应的动作。也就是说需要ActionListener的监听。
我把鼠标监听当作一个单独的类了,所以把其他所需要的动作监听放在了主类里。(见附件)
四.保存图形的自定义队列
这里,是因为我们还没有怎么接触队列,刚开始时,老师为了让我们理解的更清楚,所以才有了自定义队列。用咱们龙哥的话,就是这个队列其实就是一个容器而已。就好比如我们生活中的水桶。我们都知道,只要是个水桶,我们就能往里面装东西。所以,买个桶或自己造一个,都行。这里,我就自己搞个粗糙点的将就下哒。
五、 重绘,并且设置图形的颜色(这部分是我很纠结的地方)
1.在画的过程中,我们发现,我们已经画好的图形,只要被其他窗体覆盖,覆盖区的图形就都没有了。或者当我们把窗体放大或将窗体缩小再打开时,发现所画的图形都没有了。这主要的原因就是我们没有保存画好的图形。程序的变量都是放在内存的,而画出的图形是在缓存中的。我们所要做的就是怎么使得这些图形保存到内存里。这就是重绘过程,需要用到我们自己定义的队列了。
2.设置颜色,只是为了让图形更亮,更丰富些。
所以在窗体主类里,可以添加如下代码
ActionListener a2=new ActionListener(){
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("选颜色")){
color=JColorChooser.showDialog(null, "请选择颜色",Color.blue);
lis.c=color; //设置监听器对象的颜色
}
else if(e.getActionCommand().equals("设置窗体颜色")){
color=JColorChooser.showDialog(null, "请选择颜色",Color.blue);
c2=color;
System.out.print(c2);
datafile.cc=c2.getRGB();
System.out.println(datafile.cc);
getContentPane().setBackground(color); //设置窗体的背景颜色
}
}
};
这里a2是动作监听器的对象,可以绑定两个选择颜色的按钮为它的事件源。当鼠标点击选择颜色按钮时,就会弹出一个颜色选择器,用户就可以在选择器上任一选择一种想要的颜色。
六.图形保存成文件
之前的重绘是将画好的图形保存到内存里,而这里是将画好的图形保存在硬盘上。(暂时还只能是保存在指定的文件中)
对于所有的图形,可以知道,他们都有坐标,颜色,形状等特点。故 在保存时,就直接保存它们的这些特点就差不多了。
定义一个文件数据类。里面两个方法,分别用来是将图形的所有数据写入指定的文件中和读取文件中的数据,并同时将读取的数据保存到自定义队列中,然后将队列返回给主类。
保存到文件和读取的方法可以了,接下来就是要实现它的功能了。也就是当点击“保存”和“打开”按钮时,能够实现保存和打开的功能。所有可以在主类里添加如下代码。
//匿名内部类做监听器
ActionListener al=new ActionListener(){
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("保存")){//当事件源是“保存”按钮时
datafile.writefile(path, shapes); //调用将已经画好的图形的所有数据存入指定的文件中
}
if(e.getActionCommand().equals("撤销")){//当事件源是“撤销”按钮时
if(shapes.size()>0){ //当图形的个数大于0的时候
Shape sh=shapes.get(shapes.size()-1); //获得最后画的那个图形对象
shapes.remove(sh); //移除最后的那个对象
repaint(); //撤销最后画的图形后,刷新画图板界面
}
}
if(e.getActionCommand().equals("清零")){//当事件源是“清零”按钮时
shapes.removeall(); //移除队列中所有的对象
getContentPane().setBackground(null); //同时将窗体的颜色也去掉
repaint(); //清零后,将画图板的界面刷新
}
else if(e.getActionCommand().equals("打开")) {//当事件源是“打开”在按钮时
shapes= datafile.readfile(path); //调用读取文件的方法
Shape sh=shapes.get(1);
if(sh.c2!=0){
Color c3=new Color(sh.c2);
getContentPane().setBackground(c3); //恢复窗体的背景颜色
}
repaint(); //刷新画图板的界面
}
}
};
七.图形的撤销和清零
因为在画图的过程中,也会发现,有时候画的图形并不是自己喜欢或想要的,所有,我们就需要将画的不满意的图形撤销了。或者将本次画的所有图形清除掉。这里发生的也是动作事件了。所有可以在a1的基础上改进点就行了。
以上就基本完成了这个简单的画图板了。具体的见附近。
遇到的问题:
在整个过程中,监听器的使用与用到它的主类之间纠结了很久。还有感觉自己对文件的保存还很陌生,在测试的时候,常常是保存了,打开不了,在这里也把读取后的队列丢掉了,结果在打开这个环节磨了好久。然后讲的本质点就是对于每个类之间的连接关系扯不清。其实也就是总是被程序控制了。伤心!还需继续努力啊!