JAVA简单画图程序

1.JFrame窗体界面(JButton、Graphics、Graphics2D、Color)
创建一个Draw类,在主函数中实例化Draw类,并调用Ondraw方法

public class Draw{
    public static void main(String[] args) {
        //在主函数中,实例化Draw类的对象,调用初始化界面的方法
        Draw draw = new Draw();
        draw.Ondraw();
    }

在Ondraw中方法中对窗体进行设置、添加等操作

public void Ondraw() {

        //在初始化界面的方法中,实例化JFrame窗体容器组件类的对象
        JFrame frame = new JFrame();
        //设置窗体容器组件对象的属性值:标题、大小、显示位置、关闭操作、可见。
        frame.setTitle("画板");
        frame.setSize(700,700);
        frame.setDefaultCloseOperation(3);
        frame.setLocationRelativeTo(null);

        //实例化FlowLayout流式布局类的对象,设置对齐方式
        FlowLayout fl = new FlowLayout(FlowLayout.CENTER);
        frame.setLayout(fl);

        String[] typeArray = {"直线","矩形","圆","文字","铅笔","刷子","橡皮","喷枪","长方体"};
        for(int i=0;i<typeArray.length;i++) {
            JButton button = new JButton(typeArray[i]);
            button.setPreferredSize(new Dimension(80,30));
            frame.add(button);
        }

        Color[] colorArray = {Color.red,Color.green,Color.blue};
        for(int i=0;i<colorArray.length;i++) {
            JButton button = new JButton();
            button.setBackground(colorArray[i]);
            button.setPreferredSize(new Dimension(30,30));
            frame.add(button);
        }

        frame.setVisible(true);//显示窗体

        //获取窗体上的画笔对象
        Graphics g = frame.getGraphics();
        //在实例化DrawListener类的对象时将获取的窗体对象传递过去
        DrawListener dl = new DrawListener(frame);
        //给窗体添加鼠标事件监听方法,指定事件的处理类的对象dl;
        dl.setG(g);//设置方法将画笔g传到DrawListener
    }

}       

2.事件监听方法(ActionListener、MouseLististener、MouseMotionListener)
创建一个事件监听类DrawListener

public class DrawListener implements MouseListener,MouseMotionListener,ActionListener {

    private int x1,x2,y1,y2;//将坐标设置为属性,可以在不同的方法中使用
    //定义Graphics画笔类的对象属性名
    //Graphics2D为Graphics的子类,设置线条粗细后要使用Graphics2D来画图
private Graphics2D g;//Graphics2D为Graphics的子类,设置线条粗细后要使用Graphics2D
    //定义JFrame窗体类对象属性名,最后用来获取窗体的颜色,制作橡皮擦
    private JFrame frame;

    public DrawListener(JFrame framel) {
        this.frame = frame;
    }

    //定义一个带Graphics参数的构造方法
    public void setG(Graphics g) {
        this.g = (Graphics2D) g;
        this.g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);// 设置画笔开启抗锯齿
    }
    //重写接口MouseListener,MouseMotionListener,ActionListener中所有的抽象方法
    public void actionPerformed(ActionEvent e) {
        System.out.println("点击的按钮是:"+e.getActionCommand());
        if(e.getActionCommand().equals("")) {
            JButton button = (JButton) e.getSource();//获取事件源对象
            color = button.getBackground();//获取背景颜色
        }else {
            name=e.getActionCommand();//获取按钮信息  
        }

    public void mouseDragged(MouseEvent e){
        System.out.println("拖动");

    }

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseClicked(MouseEvent e) {
        System.out.println("点击");
    }

    public void mousePressed(MouseEvent e) {
        System.out.println("按下");
    }

    public void mouseReleased(MouseEvent e) {
        System.out.println("释放");

    }

    public void mouseEntered(MouseEvent e) {
        System.out.println("进入");
    }

    public void mouseExited(MouseEvent e) {
        System.out.println("离开");
    }

}

在Draw类中对按钮增加监听方法,即ActionListener,点击按钮时进行对应的操作
实例化事件处理类DrawListener要在添加监听方法前进行,因为添加监听方法要指定事件处理类

            String[] typeArray = {"直线","矩形","圆","文字","铅笔","刷子","橡皮","喷枪","长方体"};
            for(int i=0;i<typeArray.length;i++) {
            JButton button = new JButton(typeArray[i]);
            button.setPreferredSize(new Dimension(80,30));
            frame.add(button);
            button.addActionListener(dl);//添加动作监听方法
        }
            Color[] colorArray = {Color.red,Color.green,Color.blue};
            for(int i=0;i<colorArray.length;i++) {
            JButton button = new JButton();
            button.setBackground(colorArray[i]);
            button.setPreferredSize(new Dimension(30,30));
            frame.add(button);
            button.addActionListener(dl);//添加动作监听方法
        }

同时需要对窗体添加鼠标事件监听方法,指定事件处理类的队象

frame.addMouseListener(dl); 
frame.addMouseMotionListener(dl);

3.画图形(直线、矩形、圆、文字、铅笔、刷子、橡皮、喷枪、长方体、颜色)
在鼠标按下时获取第一个坐标值x1,y1
在鼠标释放时获取第二个坐标值x2,y2根据两个坐标值来画直线、矩形、圆

public void mousePressed(MouseEvent e) {
        System.out.println("按下");
        //在按下和释放的事件处理方法中获取按下和释放的坐标值
        x1 = e.getX();
        y1 = e.getY();
        g.setColor(color);//设置画笔颜色
}
public void mouseReleased(MouseEvent e) {
        System.out.println("释放");
        x2 = e.getX();
        y2 = e.getY();
}

获取第二个坐标值后,根据两个坐标值来画直线、矩形、圆,在鼠标释放后就可进行画图
画图前先判断要画什么图形,在调用相应的方法

public void mouseReleased(MouseEvent e) {
        System.out.println("释放");
        x2 = e.getX();
        y2 = e.getY();

        //设置画笔的颜色
        //g.setColor(Color.green);
        //g.setColor(new Color(100, 100, 100));
        //根据按下和释放的坐标值,使用Graphics对象进行画图

        g.setStroke(new BasicStroke(1));//设置线条的粗细
        switch(name) {
        case "直线":
g.drawLine(x1, y1, x2, y2);
            break;

        case "矩形":
         g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
            break;

        case "圆":
        g.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
            break;

        case "文字":
            g.drawString("大学生需要考四级", x1, y1);
            break;
        }

    }

铅笔、刷子、橡皮主要是线条粗细的不同,通过setStroke(new BasicStroke(这里为线条的值,例1,5,10等等))。
这里画图程序的橡皮是通过获取JFrame窗体的背景色来画线,覆盖掉原本的图形颜色,从而达到擦去效果。获取JFrame窗体的颜色,在Draw类中实例化DrawListener的时候把窗体传到DrawListener类中,通过color = frame.getContentPane().getBackground()获取颜色。
铅笔、刷子、橡皮都是在鼠标拖动时完成,要实现铅笔、刷子、橡皮就是是现曲线。
画曲线:

g.drawLine(x1, y1, x2, y2);
x2 = e.getX();
y2 = e.getY();
x1 = x2;
y1 = y2;

接下来实现铅笔、刷子、橡皮,在拖动时进行画图,在鼠标拖动方法下写画图方法

public void mouseDragged(MouseEvent e){
        System.out.println("拖动");
        x2 = e.getX();
        y2 = e.getY();
        switch(name) {
        case "铅笔":
            g.setStroke(new BasicStroke(2));//设置线条的粗细
            g.drawLine(x1, y1, x2, y2);//画曲线
            x1 = x2;
            y1 = y2;    
            break;
        case "刷子":
            g.setStroke(new BasicStroke(10));//设置线条的粗细
            g.drawLine(x1, y1, x2, y2);//画曲线
            x1 = x2;
            y1 = y2;    
            break;
        case "橡皮":
            color = frame.getContentPane().getBackground();
            g.setColor(color);//设置颜色为窗体颜色
            g.setStroke(new BasicStroke(50));
            g.drawLine(x1, y1, x2, y2);//画曲线
            x1 = x2;
            y1 = y2;    
            break;
        }

    }

喷枪是将所画曲线的点离散掉,需要用到随机数。

Random rand = new Random();
            for(int i=0;i<10;i++) {
                int p = rand.nextInt(10);
                int q = rand.nextInt(10);
                g.drawLine(x2+p, y2+q, x2+p, y2+q);
            }
x2 = e.getX();
            y2 = e.getY();
            x1 = x2;
            y1 = y2;

长方体需要画三个面,并且用不同的颜色进行填充显示出来。第一步,通过两个点的坐标将正面画出来,然后填充;第二步是顶面,利用两个点的坐标值算出顶面的另两个点的坐标,然后填充顶面;第三步算出右侧面的另两个点,然后填充。

            g.setColor(new Color(100, 200, 100));
            g.fillRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
            int a,b,c,d;
            a=Math.min(x1, x2);
            b=Math.max(x1, x2);
            c=Math.min(y1, y2);
            d=Math.max(y1, y2);


            int m=(int)((b-a)*Math.cos(Math.PI/4)*Math.sin(Math.PI/4));
            int n=(int)((b-a)*Math.cos(Math.PI/4)*Math.sin(Math.PI/4));
            //顶面
            g.setColor(Color.green);
            g.fillPolygon(new int[] {a, a+m, b+m,b},new int[] {c,c-n,c-n,c},4);
            //右侧面
            g.setColor(Color.black);
            g.fillPolygon(new int[] {b, b, b+m,b+m},new int[] {c,d,d-n,c-n},4);

4.重绘(数组、重写paint()方法)
在窗体上绘制图像,当改变窗体的大小后,画在窗体上的图像会消失。
原因:每当你改变窗体大小后,改变后的大小和原来的大小不一致了,窗体需要根据新的大小重新再画一次。之前画的图形是画在窗体上,重画窗体的时候,图形没有存储,并不会重画一次。
要将图形重画就要把图形存储起来
每一个图形都是由多个数据组成,并且图形不同,数据的个数也不同,定义类实现这个对象
把每一个图形对象使用数组或者队列存储起来
定义类继承JFrame窗体对象,接下来重写paint(Graphics g)方法
画窗体的方法是paint(Graphics g),在此方法中将存储的图形信息取出来再画一次
需要定义一个Paint类,图形和数据个数不同

public class Paint {
    private int x1,y1,x2,y2;
    private Color color;
    private String name;
    private int width;//线条粗细

    public Paint(int x1, int y1, int x2, int y2, Color color, String name) {
        super();
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.color = color;
        this.name = name;
    }

    public Paint(int x1, int y1, int x2, int y2, Color color, String name, int width) {
        super();
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.color = color;
        this.name = name;
        this.width = width;
    }

    //可以把方法写在这里,在Draw类和DrawLisyener类中调用

    public int getX1() {
        return x1;
    }
    public void setX1(int x1) {
        this.x1 = x1;
    }
    public int getY1() {
        return y1;
    }
    public void setY1(int y1) {
        this.y1 = y1;
    }
    public int getX2() {
        return x2;
    }
    public void setX2(int x2) {
        this.x2 = x2;
    }
    public int getY2() {
        return y2;
    }
    public void setY2(int y2) {
        this.y2 = y2;
    }
    public Color getColor() {
        return color;
    }
    public void setColor(Color color) {
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }

}

利用数组将图形信息存储起来
在Draw中定义一个数组,通过DrawLisener的实例化把数组传到DrawListener类中,把图形信息存储到数组中
Draw类中:

private Paint[] array = new Paint[1000];//定义存储图形的数组
DrawListener dl = new DrawListener(frame,array);

DrawListener类中:

private Paint[] array;//定义存储图形的数组
private int index = 0;
public DrawListener(JFrame frame,Paint[] array) {
        this.frame = frame;
        this.array = array;
}
//存储图形信息
Paint paint = new Paint(x1,y1,x2,y2,color,name,2);//根据图形的数据实例化Paint对象
            if(index<1000)
                array[index++] = paint;//将数组对象存入到数组中

定义类继承JFrame窗体对象,重写paint(Graphics g)方法,将存储的图形再画一次
继承JFrame窗体对象后,不用实例化JFrame,把全部的frame改为this

public class Draw extends JFrame{


    public static void main(String[] args) {
        //在主函数中,实例化Draw类的对象,调用初始化界面的方法
        Draw draw = new Draw();
        draw.Ondraw();
    }

    private Paint[] array = new Paint[1000];//定义存储图形的数组
    private int x1, y1, x2, y2;

    //重写父类的重绘方法
    public void paint (Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);// 设置画笔抗锯齿
        //把存储在数组中的图形数据取出来,重新画一次
        for (int i=0;i<array.length;i++) {
            Paint p = array[i];//获取数组中指定下标位置的图形对象
            if(p!=null) {
                x1=p.getX1();
                x2=p.getX2();
                y1=p.getY1();
                y2=p.getY2();

                g.setColor(p.getColor());
                if(p.getName().equals("直线")) {
                    g.drawLine(x1, y1, x2, y2); 
                } else if(p.getName().equals("矩形")) {
                    g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2),Math.abs(y1-y2));
                } else if(p.getName().equals("圆")) {
                    g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2),Math.abs(y1-y2));
                } else if(p.getName().equals("文字")) {
                    g.drawString("大学生需要考四级", x1, y1);
                } else if(p.getName().equals("铅笔")||p.getName().equals("刷子")||p.getName().equals("橡皮")) {
                    g2d.setStroke(new BasicStroke(p.getWidth()));
                    g2d.drawLine(x1, y1, x2, y2);
                } else if(p.getName().equals("喷枪")) {
                    g.drawLine(x1,y1,x2,y2);    
                } else if(p.getName().equals("长方体")) {
                    int a,b,c,d;
                    a=Math.min(x1, x2);
                    b=Math.max(x1, x2);
                    c=Math.min(y1, y2);
                    d=Math.max(y1, y2);
                    int m=(int)((b-a)*Math.cos(Math.PI/4)*Math.sin(Math.PI/4));
                    int n=(int)((b-a)*Math.cos(Math.PI/4)*Math.sin(Math.PI/4));
                    g.setColor(new Color(100, 200, 100));
                    g.fillRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2),Math.abs(y1-y2));
                    g.setColor(Color.green);
                    g.fillPolygon(new int[] {a, a+m, b+m,b},new int[] {c,c-n,c-n,c},4);
                    g.setColor(Color.black);
                    g.fillPolygon(new int[] {b, b, b+m,b+m},new int[] {c,d,d-n,c-n},4);
                }
                else
                    break;

            }
        }
    }

    public void Ondraw() {

        //在初始化界面的方法中,实例化JFrame窗体容器组件类的对象
        //JFrame frame = new JFrame();
        //设置窗体容器组件对象的属性值:标题、大小、显示位置、关闭操作、可见。
        this.setTitle("画板");
        this.setSize(700,700);
        this.setDefaultCloseOperation(3);
        this.setLocationRelativeTo(null);

        //实例化FlowLayout流式布局类的对象,设置对齐方式
        FlowLayout fl = new FlowLayout(FlowLayout.CENTER);
        this.setLayout(fl);

        //在实例化DrawListener类的对象时将获取的画笔对象传递过去
        DrawListener dl = new DrawListener(this,array);

        String[] typeArray = {"直线","矩形","圆","文字","铅笔","刷子","橡皮","喷枪","长方体"};
        for(int i=0;i<typeArray.length;i++) {
            JButton button = new JButton(typeArray[i]);
            button.setPreferredSize(new Dimension(80,30));
            this.add(button);
            button.addActionListener(dl);//添加动作监听方法
        }

        Color[] colorArray = {Color.red,Color.green,Color.blue};
        for(int i=0;i<colorArray.length;i++) {
            JButton button = new JButton();
            button.setBackground(colorArray[i]);
            button.setPreferredSize(new Dimension(30,30));
            this.add(button);
            button.addActionListener(dl);//添加动作监听方法
        }



        this.setVisible(true);

        //获取窗体上的画笔对象
        Graphics g = this.getGraphics();


        //给窗体添加鼠标事件监听方法,指定事件的处理类的对象dl;
        dl.setG(g);//设置方法将画笔g传到DrawListener
        this.addMouseListener(dl);  
        this.addMouseMotionListener(dl);
    }

}

猜你喜欢

转载自blog.csdn.net/qq1925346284/article/details/82562363