设计画图板,主要有几个方向:Java.swing中的组件,监听器,队列的使用,文件的保存。
一. 画板界面
要设计一个画图板,首先需要窗体也就是画板界面(这里包括界面的一些属性)以及配套需要的窗体组件,如Jbutton, ButtonGroup,JradioButton.
以上是一个简单的画板界面。
二. 绘制图形
想要绘制的所有图形都有共同点,它们都称之为图形,都有颜色和画的方法。所以,可以定义一个图形的父类。
三. 监听器
绘制的图形的方法可以了,我们就可以开始画图了。画图的过程就是,当鼠标点击并拖动到释放时,就能够画出图形来。所以就需要鼠标监听器,获得点击和释放时的坐标。这里为了简便画完之后就把它保存在自定义容器中。下面再说自定义队列。
四. 保存图形的自定义队列
五. 重绘,并且设置图形的颜色(这部分是我很纠结的地方)
在画的过程中,我们发现,我们已经画好的图形,只要被其他窗体覆盖,覆盖区的图形就都没有了。当我们把窗体缩小或放大时也出现类似情况。这主要的原因就是我们没有保存画好的图形。程序的变量都是放在内存的,而画出的图形是在缓存中。我们所要做的就是怎么使得这些图形保存到内存里。这就是重绘过程。
设置颜色,只是为了让图形更亮,更丰富些。
所以在窗体主类里,可以添加如下代码
这样当鼠标点击选择颜色按钮时,就会弹出一个颜色选择器,用户就可以在选择器上任一选择一种想要的颜色。
六.图形保存成文件
之前的重绘是将画好的图形保存到内存里,而这里是将画好的图形保存的硬盘上。(暂时还只是保存在指定的文件中)
对于所有的图形,可以知道,他们都有坐标,颜色,形状等特点。故 在保存时,就直接保存它们的这些特点就差不多了。
定义一个文件数据类
import java.awt.Color; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; public class datafile { /** * 将数据写入指定的文件中 */ public static void writefile(String path,NJListImp<Shape> shapes){ try{ FileOutputStream fos=new FileOutputStream(path); //定义一个文件输出流对象 DataOutputStream dos=new DataOutputStream(fos);//将文件流包装成数据类型流 //1.写入队列中的对象的个数 dos.writeInt(shapes.size()); System.out.println(shapes.size()); for(int i=0;i<shapes.size();i++){ Shape shape=shapes.get(i);//获取队列中 的一种形状 Color color=shape.getColor();//得到对象的颜色 int c=color.getRGB(); System.out.println(c); //2.写入队列中对象的颜色和类型 dos.writeInt(c); Byte type=shape.type; dos.writeByte(type); if(type==1){//如果图形时直线 Line line=(Line)shape;//将对象转化成直线 //分别获得直线的两坐标的数据 int x1=line.x1; int y1=line.y1; int x2=line.x2; int y2=line.y2; //3.写入坐标数据 dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); } else if(type==2){//如果是矩形 Rect rect=(Rect)shape; //分别获得矩形的对角两坐标的数据 int x1=rect.x1; int y1=rect.y1; int x2=rect.x2; int y2=rect.y2; //3.写入坐标数据 dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); System.out.println("--->>"); } else if(type==3){//如果是圆形 Oval oval=(Oval)shape; //分别获得圆的两坐标的数据 int x1=oval.x1; int y1=oval.y1; int x2=oval.x2; int y2=oval.y2; //3.写入坐标数据 dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); System.out.println("<<--->>"); } else{//如果是三角形 Triangle tra=(Triangle)shape; //分别获得它的三个坐标 int x1=tra.x1; int x2=tra.x2; int x3=tra.x3; int y1=tra.y1; int y2=tra.y2; int y3=tra.y3; //3.写入坐标数据 dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); dos.writeInt(x3); dos.writeInt(y3); } } dos.flush();//强制输出流 dos.close();//关闭输出流 } catch(Exception e){ e.printStackTrace(); } } /** * 读取文件中 的数据 * @param path 要读取 的文件的路径 * @return 将数据以shapes返回 */ public static NJListImp<Shape> readfile(String path){ NJListImp<Shape> shapes = new NJListImp<Shape>(); try{ //创建文件输入流 FileInputStream fis=new FileInputStream(path); //将文件输入流包装成基本数据类型流 DataInputStream dis=new DataInputStream (fis); //读取长度 int len=dis.readInt(); for(int i=0;i<len;i++){ int c=dis.readInt(); //读取颜色的rgb System.out.println(c); Color color=new Color(c);//通过RGB值得到颜色 byte type=dis.readByte();//读取图形的类型 if(type==1){//如果读取的是直线 int x1=dis.readInt();//连续读取四个int数据 int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); Line line=new Line(x1,y1,x2,y2); line.type=type; line.setColor(color); // System.out.println(x1+"---"+y1+">>"+x2+"<<<"+y2); shapes.add(line); System.out.println(shapes.size()); } if(type==2){//如果读取的是矩形 int x1=dis.readInt();//连续读取四个int数据 int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); Rect rect=new Rect(x1,y1,x2,y2); rect.type=type; rect.setColor(color); shapes.add(rect); } if(type==3){ //如果读取的是圆形 //连续读取四个int数据 int x1=dis.readInt(); int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); Oval oval=new Oval(x1,y1,x2,y2); oval.type=type; oval.setColor(color);//设置图形的颜色 System.out.println(x1+"---"+y1+">>"+x2+"<<<"+y2); shapes.add(oval); } else if(type==0){ //如果是三角形 //连续读取六个int数据 int x1=dis.readInt(); int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); int x3=dis.readInt(); int y3=dis.readInt(); Triangle tra=new Triangle(x1,y1,x2,y2); tra.setColor(color); tra.x3=x3; tra.y3=y3; shapes.add(tra); } } dis.close();//关闭输入流 } catch(Exception e){ e.printStackTrace(); } return shapes; } }
保存的方法可以了,接下来就是要实现它。也就是当点击“保存”和“打开”按钮时,能过实现功能。所有可以在这类里添加如下代码。
//匿名内部类做监听器 ActionListener al=new ActionListener(){ public void actionPerformed(ActionEvent e){ if(e.getActionCommand().equals("保存")){ datafile.writefile(path, shapes); } else { shapes= datafile.readfile(path); repaint(); System.out.println(path); } } }; //分别给两个按钮添加监听器 button1.addActionListener(al); button2.addActionListener(al);
以上就基本完成了这个简单的画图板了。感觉自己对文件的保存还很陌生,然后就是对于每个类之间的连接关系扯不清。特别是引用传参不明白。还需继续努力啊!