zoukankan      html  css  js  c++  java
  • 画图小工具第二篇

    一、事件源

    事件源是一个事件的起点。所有的容器组件类和元素组件类可以成为事件源对象。在程序中可以有多个事件,也就是可以有多个事件源。由需要实现的功能,达到的目的来确定事件源。在程序中动作发生在哪里,哪个就是事件源。

    二、事件监听方法:

    由事件源来确定事件监听方法。

    三、事件接口:

    由事件接口实现事件监听方法,而事件接口不能实例化。所以靠定义一个事件处理来,来实现接口中的抽象方法。

    四、本次任务:

    实现曲线、刷子、橡皮、喷枪

    (在窗体上按下鼠标按键、然后拖动鼠标,在按下和拖动之间绘制曲线)

    五、实现步骤:

    1. 确定事件源:窗体。
    2. 事件监听方法:addMouseListener (MouseListener l)监听鼠标按下的动作;

    addMouseMotionListener(MouseMotionListener l)监听鼠标拖动的动作

        3.事件接口:MouseListener,MouseMouseListener。

    在上一篇的基础上实现曲线、刷子、橡皮、喷枪。

    (1):

      private Graphics2D g1;// 声明一个画布类的对象;Graphics2D是Graphics的一个子类。

     

     六、代码:

    (一):LoginListener.java

    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    /**
     * 1.新建一个LoginListener事件处理类,
     * 该类实现MouseListener鼠标事件接口,实现接口中的抽象方法。
     * 2.定义四个变量,在按下和释放方法中获取按下和释放的坐标值。
        3.定义Graphics画笔画布类的对象,调用绘制图形的方法来画图。
            我们的组件是画出来的,那么你要在哪一个组件上画图形,那你的画笔画布对象就从这个组件上获取。
        4.实例化DrawListener事件处理类的对象,对象名dl
        5.给事件源窗体对象添加addMouseListener()鼠标监听方法,指定事件处理类对象dl.
    
     */
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.util.Random;
    
    //F3键可以看到代码
    public class LoginListener implements MouseListener, ActionListener, MouseMotionListener {
    
        public String s;
    
        private int X1, X2, Y1, Y2;// 声明四个整数变量,用来记录按下和释放时的坐标值
    
        public int sx,sy,ex,ey;//存储任意多边形的起始点坐标和结束点的坐标
        public int count=0;//记录画的是任意多边形的第几条线
    
        Graphics g;// 声明一个画笔画布类的对象名
        // 向DrawFrame借画笔画布类的对象。
        // public JButton butLine ;
        // public JButton butSquare;
        // public JButton butRotundity;不需要用到方法和属性,所以不用声明对象。
        // public JButton butS;
        private Graphics2D g1;// 声明一个画布类的对象;Graphics2D是Graphics的一个子类。
        BasicStroke S = new BasicStroke(10);
        BasicStroke C = new BasicStroke(1);// 方法一:实例化画笔粗细。设置画笔粗细为1.
    
        public void SetG(Graphics gra) {
            g = gra;// 把gra给g;
            g1 = (Graphics2D) gra;// 强制转型
    
            g1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 设置设置画笔抗锯齿,使线条更加平滑。
        }
    
        // public void SetJ(JButton jb){
        // butLine=jb ; 没有用到对象的方法或者属性就不用传。
        // butSquare=jb;
        // butRotundity=jb;
        // butS=jb;
        // }
        /**
         * 当你在事件源上发生鼠标按下动作时执行的方法。
         */
    
        public void mousePressed(MouseEvent e) {
            // 取得鼠标按下时取得的坐标;
            X1 = e.getX();
            Y1 = e.getY();
    
        }
    
        /**
         * 当你在事件源上发生鼠标释放动作时执行的方法。
         */
        public void mouseReleased(MouseEvent e) {
    
            X2 = e.getX();
            Y2 = e.getY();
    
            if (s.equals("直线")) {
    
                g.drawLine(X1, Y1, X2, Y2);
    
            }
            if (s.equals("圆")) {
    
                g.drawOval(X1, Y1, X2, Y2);
            }
            if (s.equals("矩形")) {
                g.drawRect(X1, Y1, X2, Y2);
    
            }
            if (s.equals("任意多边形") && count==0) {//判断是否画任意多边形的第一条线
    
                g.drawLine(X1, Y1, X2, Y2);
                //存储第一条线的起始点
                sx = X1;
                sy = Y1;
                //存储第一条线的结束点
                ex = X2;
                ey = Y2;
                
                count++;//表示第一条已经画完了
            }
    
        }
    
        /**
         * 当你的鼠标进入到事件源是行时执行的方法。
         */
        public void mouseEntered(MouseEvent e) {
    
        }
    
        /**
         * .当你的鼠标离开到事件源是行时执行的方法。
         */
        public void mouseExited(MouseEvent e) {
    
        }
    
        /**
         * 当你在事件源上发生鼠标点击动作时执行的方法。(在同一个位置上按下并释放才会执行点击)
         */
    
        public void mouseClicked(MouseEvent e) {
            if (s.equals("任意多边形") && count!=0) {//判断是否已经画完任意多边形的第一条线了
                //获取点击的坐标值
                int x = e.getX();
                int y = e.getY();
                if(e.getClickCount()==2){//判断是双击,图形要闭合
                    //使用x,y和ex,ey画闭合的第一条线
                    g.drawLine(ex, ey, x, y);
                    //使用x,y和sx,sy画闭合图形的最后 一条线
                    g.drawLine(sx, sy, x, y);
                    //改变count的值,好让下一次又是重新开始新的多边形
                    count=0;
                }else{//判断不是双击,要接下来的线
                    //根据上一条线的结束点和当前点击的坐标,来绘制直线
                    g.drawLine(ex, ey, x, y);
                    //将当前这条线的结束赋给ex,ey,作为下一条线的起始点
                    ex = x;
                    ey = y;
                }
            }
        }
    
        public void actionPerformed(ActionEvent e) {
            // 得到按钮上的文字;
            s = e.getActionCommand();
    
            // getActionCommand()的方法是ActionEvent的,也就是e的。
    
        }
    
        @Override // 当鼠标拖动时,在事件源上按下鼠标按键然后拖动鼠标时执行的方法。
        public void mouseDragged(MouseEvent e) {
            if (s.equals("画笔")) {
                /**
                 * 因为在拖动过程当中会不断取点,如果起点固定则画出来的都是在一个点开始的。
                 * 以上一个拖动取到的坐标作为下一段直线的起点,从而画出曲线。
                 */
    
                X2 = e.getX();
                Y2 = e.getY();
                g1.drawLine(X1, Y1, X2, Y2);
                X1 = X2;// 转换坐标。
                Y1 = Y2;
    
            }
            if (s.equals("刷子")) {
    
                g1.setStroke(S);// 要进行转换画笔,再画;设置线条的粗细。
                X2 = e.getX();
                Y2 = e.getY();
                g1.drawLine(X1, Y1, X2, Y2);
                X1 = X2;
                Y1 = Y2;
                g1.setStroke(C);
    
            }
            if (s.equals("橡皮擦")) {
                g1.setStroke(S);
                g1.setColor(Color.WHITE); // 设置线条的颜色为白色来绘制橡皮擦。
                X2 = e.getX();
                Y2 = e.getY();
                g1.drawLine(X1, Y1, X2, Y2);
                X1 = X2;
                Y1 = Y2;
                g1.setColor(Color.black);// 在画完之后转换回一般的格式就可以不用在每个都设置。粗细也是。
                g1.setStroke(new BasicStroke(1));// 设置粗细法二。
    
            }
            if (s.equals("喷枪")) {//(难点)
                g1.setStroke(C);
                X2 = e.getX();
                Y2 = e.getY();
    
                Random rand = new Random();// 实例化一个随机数类的对象
                int size = rand.nextInt(50) + 20;// 随机决定要画的点数,size的范围在20到69之间。没有“+20”时,只有0到49之间
                for (int i = 0; i < size; i++) {
                    int x = rand.nextInt(8);// 在0到7之间随机取点。
                    int y = rand.nextInt(8);
                    g1.drawLine(X2 + x, Y2 + y, X2 + x, Y2 + y);// 有随机数来改变坐标,在X2,Y2附件画点。
                }
    
                g1.setColor(Color.black);
                g1.setStroke(C);
    
            }
    
        }
    
        @Override
        /*
         * 当在事件源上移动鼠标时执行的方法。
         */
        public void mouseMoved(MouseEvent e) {
    
        }
    
    }

    (二)DrawFrame.java

    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.text.AbstractDocument.Content;
    
    /**
     * 定义一个画图界面类,该类继承自JFrame窗体类.
     */
    public class DrawFrame extends JFrame {
    
        /**
         * 程序入口主函数
         */
        public static void main(String[] args) {
            // 实例化窗体类的对象,调用初始化界面的方法
            DrawFrame dl = new DrawFrame();
            dl.initUN();
            // dl.setBackground(Color.WHITE);这个是错误的不能改变窗体的颜色。
    
        }
    
        public void initUN() {
            setTitle("简单画图");
            setSize(600, 500);
            setDefaultCloseOperation(3);
            setLocationRelativeTo(null);
            setLayout(new FlowLayout());
            JButton butLine = new JButton("直线");
            this.add(butLine);
            JButton butSquare = new JButton("矩形");
            add(butSquare);
            JButton butRotundity = new JButton("圆");
            add(butRotundity);
            JButton butS = new JButton("任意多边形");
            add(butS);
            JButton but = new JButton("画笔");
            add(but);
            JButton butt = new JButton("刷子");
            add(butt);
            JButton but1 = new JButton("橡皮擦");
            add(but1);
            JButton but2 = new JButton("喷枪");
            add(but2);
            getContentPane().setBackground(Color.WHITE);//getContenPane为 改变窗口的颜色。
    
            /**
             * //实例化一个流失布局类的对象,布局类是针对容器的,容器上要填多个组件,那么必须要设置排列对齐方式;
             * java.awt.FlowLayout fl=new java.awt.FlowLayout();
             * jf.setLayout(fl);//设置窗体的布局方式为流式布局 //定义一个ImageIcon类,该类用来读取一个磁盘的图片文文件。
             */
    
            setVisible(true);
    
            Graphics g = getGraphics();// 获取窗体上画笔画布对象(注意:必须要在窗体可见之后才能获取画笔画布对象,否则获取的是null)
    
            // 4.在DrawFrame类中实例化LoginListener事件处理类的对象dn;
            LoginListener dn = new LoginListener();
            addMouseListener(dn);// 5.给事件源窗体对象添加addMouseListener()鼠标监听方法,指定事件处理类对象dl.
            addMouseMotionListener(dn);
            butLine.addActionListener(dn);// 要加监听方法才能获取数值。
            butSquare.addActionListener(dn);// 要加监听方法才能获取数值。
            butRotundity.addActionListener(dn);// 要加监听方法才能获取数值。
            butS.addActionListener(dn);// 要加监听方法才能获取数值。
            but1.addActionListener(dn);
    
            but.addActionListener(dn);
            butt.addActionListener(dn);
            but2.addActionListener(dn);
    
            dn.SetG(g);
    
            // dl.SetJ(butS);
            // dl.SetJ(butRotundity);
            // dl.SetJ(butSquare);
            // dl.SetJ(butLine);
    
        }
    
    }

    七:注意点

    g1 = (Graphics2D) gra;// 强制转型
    子类到父类是强制转型;
    父类到子类是自动转型;
    设置线条的颜色为白色来绘制橡皮擦。(原来想的是把取到的数据归零但是发现画不了。)
    因为在拖动过程当中会不断取点,如果起点固定则画出来的都是在一个点开始。以上一个拖动取到的坐标作为下一段直线的起点,从而画出曲线。
    本次的难点是喷枪:
    之前画的喷枪是一段白线加上黑线,并没有达到效果。后来是利用了随机数点来画。

    鼠标点下时,随机在该点旁边画下点。
    Random rand = new Random();// 实例化一个随机数类的对象
    int size = rand.nextInt(50) + 20;// 随机决定要画的点数,size的范围在20到69之间。没有“+20”时,只有0到49之间
    for (int i = 0; i < size; i++) {
    int x = rand.nextInt(8);// 在0到7之间随机取点。
    int y = rand.nextInt(8);
    g1.drawLine(X2 + x, Y2 + y, X2 + x, Y2 + y);// 有随机数来改变坐标,在X2,Y2附件画点。
    八:运行结果
     

     
  • 相关阅读:
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
    java io系列20之 PipedReader和PipedWriter
    java io系列19之 CharArrayWriter(字符数组输出流)
    java io系列18之 CharArrayReader(字符数组输入流)
    java io系列17之 System.out.println("hello world")原理
    java io系列16之 PrintStream(打印输出流)详解
    java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
    java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
  • 原文地址:https://www.cnblogs.com/hesi/p/5575957.html
Copyright © 2011-2022 走看看