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

}

源码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.BasicStroke;
import javax.swing.JButton;
import javax.swing.JFrame;


public class Draw extends JFrame{
   

	public static void main(String[] args) {
   
		//在主函数中,实例化Draw类的对象,调用初始化界面的方法
		Draw draw = new Draw();
		draw.Ondraw();
	}
	
	private Paint[] array = new Paint[100000];//定义存储图形的数组
	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
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值