简单画图板

设计画图板,主要有几个方向:Java.swing中的组件,监听器,队列的使用,文件的保存。

一.     画板界面

要设计一个画图板,首先需要窗体也就是画板界面(这里包括界面的一些属性)以及配套需要的窗体组件Jbutton, ButtonGroup,JradioButton. 

 

Java代码 复制代码
  1. package  draw;   
  2.   
  3. import java.awt.FlowLayout;   
  4.   
  5. import java.awt.Graphics;   
  6.   
  7. import javax.swing.JFrame;   
  8.   
  9. /**  
  10.  
  11.  *画板窗体类  
  12.  
  13.  * @author Administrator  
  14.  
  15.  *   
  16.  
  17.  */  
  18.   
  19. public class draws extends JFrame {   
  20.   
  21. /**  
  22.  
  23.      * 程序入口  
  24.  
  25.      *   
  26.  
  27.      * @param args  
  28.  
  29.      */  
  30.   
  31.     public static void main(String[] args) {   
  32.   
  33.    //创建一个draws窗体的对象   
  34.   
  35.        draws ds = new draws();   
  36.   
  37.        ds.dra();   
  38.   
  39.     }   
  40.   
  41.     
  42.   
  43. /**  
  44.  
  45.      * 显示画板窗体的方法  
  46.  
  47.      */  
  48.   
  49. public void dra() {   
  50.   
  51. // 设置窗体的属性   
  52.   
  53.        this.setTitle("简单画图板");//设置标题   
  54.   
  55.        this.setBounds(100100500400);//设置大小   
  56.   
  57.        this.setDefaultCloseOperation(3); //关闭时退出程序   
  58.   
  59.        this.setLayout(new FlowLayout());//设置布局   
  60.   
  61.        this.setLocationRelativeTo(null);   
  62.   
  63.        this.setResizable(false);   
  64.   
  65.          //定义两个按钮,保存和打开   
  66.   
  67.        JButton  button1=new JButton("保存");   
  68.   
  69.        JButton  button2=new JButton("打开");   
  70.   
  71.         //定义两个面板   
  72.   
  73.        JPanel  p=new JPanel();   
  74.   
  75.        JPanel  p2=new JPanel();   
  76.   
  77.        p2.add(button1);p2.add(button2);//将两个按钮添加到南面的面板上   
  78.   
  79.        
  80.   
  81.        javax.swing.JButton btnColor = new javax.swing.JButton("颜色");   
  82.   
  83.        this.add(btnColor);      // 创建一个按钮组   
  84.   
  85.        javax.swing.ButtonGroup group = new javax.swing.ButtonGroup();   
  86.   
  87.     
  88.   
  89.        javax.swing.JRadioButton line = new javax.swing.JRadioButton("Line");   
  90.   
  91.        line.setActionCommand("Line");   
  92.   
  93.        line.setSelected(true);// 默认选中   
  94.   
  95.     
  96.   
  97. javax.swing.JRadioButton  triangle= new javax.swing.JRadioButton("Triangle");   
  98.   
  99.        triangle.setActionCommand("Triangle");   
  100.   
  101.     
  102.   
  103.        javax.swing.JRadioButton rect = new javax.swing.JRadioButton("Rect");   
  104.   
  105.        rect.setActionCommand("Rect");   
  106.   
  107.     
  108.   
  109.        javax.swing.JRadioButton oval = new javax.swing.JRadioButton("Oval");   
  110.   
  111.        oval.setActionCommand("Oval");   
  112.   
  113.     
  114.   
  115.        //将四个按钮加入到组中   
  116.   
  117.         group.add(line);   
  118.   
  119.         group.add(triangle);   
  120.   
  121.        group.add(rect);   
  122.   
  123.        group.add(oval);   
  124.   
  125.           
  126.   
  127.        p.add(b);//将颜色按钮添加到面板p上   
  128.   
  129.        p.add(line); //将三个按钮添加到面板上   
  130.   
  131.        p.add(triangle);   
  132.   
  133.        p.add(rect);   
  134.   
  135.        p.add(oval);   
  136.   
  137.        p.setBackground(Color.gray);//设置面板的背景颜色   
  138.   
  139.        p2.setBackground(Color.LIGHT_GRAY);   
  140.   
  141.         this.add(p2,BorderLayout.SOUTH);   
  142.   
  143.        this.add(p,BorderLayout.NORTH);//将面板添加到窗体上   
  144.   
  145.     }   
  146. }  

 

以上是一个简单的画板界面。

二.     绘制图形

想要绘制的所有图形都有共同点,它们都称之为图形,都有颜色和画的方法。所以,可以定义一个图形的父类。

 

Java代码 复制代码
  1. package  draw;   
  2.   
  3. import java.awt.Color;   
  4.   
  5. import java.awt.Graphics;   
  6.   
  7. /**  
  8.  
  9.  * 形状抽象类,所有的形状都必须继承的类  
  10.  
  11.  * @author Administrator  
  12.  
  13.  *  
  14.  
  15.  */  
  16.   
  17. public abstract class Shape {   
  18.   
  19.     private Color c;//颜色   
  20.   
  21.     /**  
  22.  
  23.      *设置颜色的方法  
  24.  
  25.      * @param c 得到颜色对象  
  26.  
  27.      */  
  28.   
  29.     public void setColor(Color c){   
  30.   
  31.        this.c = c;   
  32.   
  33.     }   
  34.   
  35.     /**  
  36.  
  37.      * 得到颜色的方法  
  38.  
  39.      * @return 返回选中的颜色  
  40.  
  41.      */  
  42.   
  43.     public Color getColor(){   
  44.   
  45.        return c;   
  46.   
  47.     }   
  48.   
  49.     /**  
  50.  
  51.      * 绘制形状的抽象方法  
  52.  
  53.      * @param g  画布对象  
  54.  
  55.      */  
  56.   
  57.     public abstract void draw(Graphics g);   
  58.   
  59. }   
  60.   
  61.  父类定义好了,接下来就是想要画的各种图形(只列出两种图形)   
  62.   
  63. package draw;   
  64.   
  65. import java.awt.Graphics;   
  66.   
  67. /**  
  68.  
  69.  * 直线类,继承Shape  
  70.  
  71.  * @author Administrator  
  72.  
  73.  *  
  74.  
  75.  */  
  76.   
  77. public class Line extends Shape{   
  78.   
  79.        
  80.   
  81.     private int x1,y1,x2,y2;   
  82.   
  83.     /**  
  84.  
  85.      * 定义画直线的方法  
  86.  
  87.      * @param x1  
  88.  
  89.      * @param y1  
  90.  
  91.      * @param x2  
  92.  
  93.      * @param y2  
  94.  
  95.      */  
  96.   
  97.     public Line(int x1,int y1,int x2,int y2 ){   
  98.   
  99.        this.x1 = x1;   
  100.   
  101.        this.y1 = y1;   
  102.   
  103.        this.x2 = x2;   
  104.   
  105.        this.y2 = y2;   
  106.   
  107.     }   
  108.   
  109.     
  110.   
  111.     /**  
  112.  
  113.      * 重写父类中的方法  
  114.  
  115.      */  
  116.   
  117.     public  void draw(Graphics g){   
  118.   
  119. //     /设置画布颜色   
  120.   
  121.        g.setColor(this.getColor());   
  122.   
  123.        g.drawLine(x1, y1, x2, y2);   
  124.   
  125.     }      
  126.   
  127. }   
  128.   
  129.   package  draw;   
  130.   
  131.     
  132.   
  133. import java.awt.Graphics;   
  134.   
  135. /**  
  136.  
  137.  * 定义一个椭圆形的子类,继承父类shape  
  138.  
  139.  * @author Administrator  
  140.  
  141.  *  
  142.  
  143.  */  
  144.   
  145. public class Oval extends Shape{   
  146.   
  147. private int x1,y1,x2,y2;   
  148.   
  149.     /**  
  150.  
  151.      * 定义画椭圆的方法  
  152.  
  153.      * @param x1  椭圆的边框坐标  
  154.  
  155.      * @param y1  
  156.  
  157.      * @param x2  
  158.  
  159.      * @param y2  
  160.  
  161.      */  
  162.   
  163.     public Oval(int x1,int y1,int x2,int y2 ){   
  164.   
  165.        this.x1 = x1;   
  166.   
  167.        this.y1 = y1;   
  168.   
  169.        this.x2 = x2;   
  170.   
  171.        this.y2 = y2;   
  172.   
  173.     }   
  174.   
  175.     /**  
  176.  
  177.      * 重写父类中的方法  
  178.  
  179.      */  
  180.   
  181.     public void draw(Graphics g){   
  182.   
  183.        g.setColor(this.getColor());//设置颜色   
  184.   
  185.        //绘制图形时,都是从左上角开始   
  186.   
  187.        if(x1<x2&&y1<y2)   
  188.   
  189.            g.drawOval(x1, y1, x2-x1, y2-y1);   
  190.   
  191.        else if(x1<x2&&y1>y2)   
  192.   
  193.            g.drawOval(x1, y2, x2-x1, y1-y2);   
  194.   
  195.        else if(x1>x2&&y1<y2)   
  196.   
  197.            g.drawOval(x2, y1, x1-x2, y2-y1);   
  198.   
  199.        else    
  200.   
  201.            g.drawOval(x2, y2, x1-x2, y1-y2);   
  202.   
  203.     }   
  204.   
  205. }  

 

三.     监听器

绘制的图形的方法可以了,我们就可以开始画图了。画图的过程就是,当鼠标点击并拖动到释放时,就能够画出图形来。所以就需要鼠标监听器,获得点击和释放时的坐标。这里为了简便画完之后就把它保存在自定义容器中。下面再说自定义队列。

 

监听器类代码 复制代码
  1.  package draw;   
  2.   
  3. import java.awt.Graphics;   
  4.   
  5. import java.awt.event.MouseEvent;   
  6.   
  7. import java.awt.event.MouseListener;   
  8.   
  9. import javax.swing.ButtonGroup;   
  10.   
  11. public class drawL implements MouseListener{   
  12.   
  13.      private int x1,y1,x2,y2;   
  14.   
  15.      private Graphics g;   
  16.   
  17.      private String s;   
  18.   
  19.      private ButtonGroup group;   
  20.   
  21.      private NList<Shape>  shapes;   
  22.   
  23.      /**   
  24.   
  25.       * 构造方法   
  26.   
  27.       * @param g 画布对象   
  28.   
  29.       * @param group  选中的图形   
  30.   
  31.       * @param shapes  自定义队列的容器   
  32.   
  33.       */   
  34.   
  35.      public drawL(Graphics g,ButtonGroup group,NList<Shape>  shapes){   
  36.   
  37.         this.g=g;   
  38.   
  39.        this.group=group;   
  40.   
  41.         this.shapes=shapes;   
  42.   
  43.      }   
  44.   
  45.      /**   
  46.   
  47.       * 获得鼠标点击时的坐标   
  48.   
  49.       */   
  50.   
  51.    public void mousePressed(MouseEvent e){   
  52.   
  53.         x1=e.getX();   
  54.   
  55.         y1=e.getY();   
  56.   
  57.         }   
  58.   
  59.         /**   
  60.   
  61.          * 获得鼠标释放时的坐标,并画出所需的图形   
  62.   
  63.          */   
  64.   
  65.         public void mouseReleased(MouseEvent e){   
  66.   
  67.         x2=e.getX();   
  68.   
  69.         y2=e.getY();         
  70.   
  71.         //定义一个字符串用来表示获得的图形的名字   
  72.   
  73.         String s=group.getSelection().getActionCommand();   
  74.   
  75.          Shape  sha=null;   
  76.   
  77.          //根据选中的图形,类创建图形对象   
  78.   
  79.         if("Line".equals(str)){   
  80.   
  81.             sh = new Line(x1,y1,x2,y2);   
  82.   
  83.        }   
  84.   
  85.        if("Rect".equals(str)){   
  86.   
  87.            sh = new Rect(x1,y1,x2,y2);   
  88.   
  89.        }   
  90.   
  91.        if("Oval".equals(str)){   
  92.   
  93.            sh=new Oval(x1,x2,y1,y2);   
  94.   
  95.        }   
  96.   
  97.        if("Triangle".equals(str))   
  98.   
  99.            sh=new  Triangle(x1,y1,x2,y2);   
  100.   
  101.         //图形的对象调用画的方法   
  102.   
  103.         sha.draw(g);   
  104.   
  105.            //将画过的形状对象保存到队列   
  106.   
  107.        shapes.add(sha);         
  108.   
  109.         }   
  110.   
  111.         public void mouseEntered(MouseEvent e){}   
  112.   
  113.         public void mouseExited(MouseEvent e){}   
  114.   
  115.         public void mouseClicked(MouseEvent e){}   
  116.   
  117. }   

 四.     保存图形的自定义队列

 

自定义队列代码 复制代码
  1.  package draw;   
  2.   
  3. /**   
  4.   
  5.  * 定义一个自定义队列的接口的实现类   
  6.   
  7.  * @author Administrator   
  8.   
  9.  *   
  10.   
  11.  */   
  12.   
  13. public class NList<E> {   
  14.   
  15.     /**   
  16.   
  17.      * 定义一个添加元素的方法   
  18.   
  19.      */   
  20.   
  21.     public void add(E e){   
  22.   
  23.        //定义一个新数组对象   
  24.   
  25.        Object temp [] = new Object[this.stu.length+1];   
  26.   
  27.        //循环将原始数组中的值拷贝到新的数组中   
  28.   
  29.        for(int i=0;i<this.stu.length;i++){   
  30.   
  31.            temp[i] = this.stu[i];   
  32.   
  33.        }   
  34.   
  35.        //将要添加的值,追加到新数组的末尾   
  36.   
  37.        temp[this.stu.length] = e;   
  38.   
  39.        //将新数组赋给原始数组   
  40.   
  41.        this.stu = temp;   
  42.   
  43.     }      
  44.   
  45.     /**   
  46.   
  47.      * 定义一个返回指定索引位值得方法   
  48.   
  49.      */   
  50.   
  51.     public E get(int index){   
  52.   
  53.        return   (E)stu[index];   
  54.   
  55.     }   
  56.   
  57.     /**   
  58.   
  59.      * 定义一个返回值存储元素个数的方法   
  60.   
  61.      */   
  62.   
  63.     public int size(){   
  64.   
  65.        return stu.length;   
  66.   
  67.     }      
  68.   
  69.     //定义一个数组   
  70.   
  71.     private Object  stu [] = new Object[0];   
  72.   
  73. }  

 

五.      重绘,并且设置图形的颜色(这部分是我很纠结的地方)

在画的过程中,我们发现,我们已经画好的图形,只要被其他窗体覆盖,覆盖区的图形就都没有了。当我们把窗体缩小或放大时也出现类似情况。这主要的原因就是我们没有保存画好的图形。程序的变量都是放在内存的,而画出的图形是在缓存中。我们所要做的就是怎么使得这些图形保存到内存里。这就是重绘过程。

 

重绘代码 复制代码
  1. //重写父类绘制窗体的方法   
  2.   
  3.     public void paint(Graphics g){   
  4.   
  5.        //调用父类的方法来绘制窗体   
  6.   
  7.        super.paint(g);   
  8.   
  9.           
  10.   
  11.        //将队列中的形状取出来绘制   
  12.   
  13.        for(int i=0;i<shapes.size();i++){   
  14.   
  15.            //根据下标取出一个形状对象   
  16.   
  17.            Shape sh = shapes.get(i);   
  18.   
  19.            //绘制   
  20.   
  21.            sh.draw(g);   
  22.   
  23.        }      
  24.   
  25.     }  

 

    设置颜色,只是为了让图形更亮,更丰富些。

所以在窗体主类里,可以添加如下代码

 

设置颜色代码 复制代码
  1. JButton b=new JButton("选颜色");//设置颜色按钮   
  2.   
  3.        b.addActionListener(new ActionListener(){   //设置颜色按钮的事件监听器   
  4.   
  5.                   public void actionPerformed(ActionEvent e){   
  6.   
  7.                       color=JColorChooser.showDialog(null, "请选择颜色",Color.blue);   
  8.   
  9.                      lis.c=color;   
  10.   
  11.                      }   
  12.   
  13.             });   
  14.   
  15. p.add(b);//添加到窗体上  

 

这样当鼠标点击选择颜色按钮时,就会弹出一个颜色选择器,用户就可以在选择器上任一选择一种想要的颜色。

 

六.图形保存成文件

之前的重绘是将画好的图形保存到内存里,而这里是将画好的图形保存的硬盘上。(暂时还只是保存在指定的文件中)

 对于所有的图形,可以知道,他们都有坐标,颜色,形状等特点。故 在保存时,就直接保存它们的这些特点就差不多了。

 定义一个文件数据类

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);

 

以上就基本完成了这个简单的画图板了。感觉自己对文件的保存还很陌生,然后就是对于每个类之间的连接关系扯不清。特别是引用传参不明白。还需继续努力啊!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值