java中画图板的基本实现

1.首先是通过JFrame写一个画图面板的界面。

           (1)需要给界面添加一个监听器,用来获取鼠标按下和释放时候的坐标。这个不能使用动作监听器(ActionListener),只有使用鼠标监听器(MouseListener)才能够获取到坐标。

 

                ActionListener:可以给需要关注其动作的组件(如Button)添加监听器(addActionListener(this);),之后在事件处理方法(public void actionPerformed(ActionEvent event){})中,对每个事件进行不同处理。

                MouseListener:用于接收组件上“感兴趣”的鼠标事件(按下、释放、单击、进入或离开)的侦听器接口。(要跟踪鼠标移动和鼠标拖动,请使用 MouseMotionListener。)旨在处理鼠标事件的类要么实现此接口(及其包含的所有方法),要么扩展抽象类 MouseAdapter(仅重写所需的方法)。

            (2)为了绘制出一个形状,我们还需要获取绘制权限获取画笔对象,这个权限在java中叫做Graphics对象,或者叫画布对象。我们可以从窗体上获取这个对象,然后创建一个鼠标监听器对象,把画布对象传给监听器。最后给窗体就加上鼠标监听器对象,这样我们在窗体上按下和释放鼠标的时候,就会获取到这两个位置的坐标。最后调用画布对象绘制的方法(对象.drawline())

2.重新定义一个类,即事件处理类(如DrawMouse),继承接口MouseListener, ActionListener,MouseMotionListener。

              (1)首先实例化一个Graphics对象来接受传过来的画笔对象。

	private Graphics gr;//创建画笔

	public void setGraphics(Graphics g) { // 创建对象,初始化
		gr = g;
	}

             (2)由于使用的是字符串数组来储存画图按钮上面的字符串(即图形名字),以及Color类的数组储存按钮的背景颜色,所以在重写ActionListener接口中的actionPerformed方法时,要首先获取按钮上的颜色或者文字,当获取的不是文字时,说明点击的是颜色按钮,读取按钮的颜色后给设置画笔的颜色;如果读取的是文字时,需要继续下一步的操作,实现代码如下:

                  e.getSource()方法依赖于事件对象。

                          比如:JButton jbt = new JButton("直线");中事件对象就是jbt

                  e.getActionCommand()方法依赖于按钮上的字符串

                          比如:JButton jbt = new JButton("直线");中字符串button

                  简而言之:用e.getSource()得到的是jbt,而用e.getActionCommand()得到的是button。

               (3)重写实现其他继承的方法

                        java中有许多绘制图形的方法,画图需要获取一定数量的坐标值x,y。在继承的接口的方法中有MouseEvent类型的形参e,可以通过形参调用getx(),gety()来获取经过某种操作(如点击,释放,单击)过后当前位置的x坐标以及y坐标。

                       用画笔的实例化对象调用drawline(x1,y1,x2,y2)方法可以画一条直线

	public void mousePressed(MouseEvent e) {
		System.out.println("按下");
			x1 = e.getX();
			y1 = e.getY();
}
	public void mouseReleased(MouseEvent e) {
		System.out.println("释放");
            x2 = e.getX();
			y2 = e.getY();
		if (name.equals("直线")) {
			gr.drawLine(x1, y1, x2, y2);
		}
		if (name.equals("椭圆")) {
			gr.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
		}
}

                             使用画笔对象gr调用drawRext()的方法画矩形(圆形同理,圆形是通过绘制矩形的方法绘制内切圆形)。需要注意的是坐标(x1,y1)代表的是矩形左上角的点,即x1,y1均是最小值。因此需要math类取大小值,绝对值。

                              由于java中没有定义画三角形的函数,所以需要通过一个变量的操作来控制花三条直线的方法来实现。多边形同理

private int count = 1;
	public void mouseClicked(MouseEvent e) {
		System.out.println("单击");
		if (name.equals("三角形") && count == 2) {
			x3 = e.getX();
			y3 = e.getY();
			gr.drawLine(x2, y2, x3, y3);
			if (e.getClickCount() == 2) {
				gr.drawLine(x1, y1, x3, y3);
				count = 1;
			}
		}
	public void mousePressed(MouseEvent e) {
		System.out.println("按下");
		if (count == 1) {
			x1 = e.getX();
			y1 = e.getY();

		}
	public void mouseReleased(MouseEvent e) {
		System.out.println("释放");
		if (count == 1) {
			x2 = e.getX();
			y2 = e.getY();
		if (name.equals("三角形") && count == 1) {
			gr.drawLine(x1, y1, x2, y2);
		}
    }

3.重绘

              在创建窗体时我们已经定义了窗体的大小,如果我们再次改变窗体大小的时候,原来的窗体就不满足显示的需求。这时候就会将窗体上所有的组件再重新绘制一次,自动调用了paint方法,这个方法是定义在JFrame和JPanel中都有的。因此必须让窗体类继承JFrame类或者JPanel类,再重写paint()方法。

              但是由于可能改变窗体大小之前已经绘制了不少图形,会有较多坐标需要保存重绘,所以需要新建一个对象数组用来存储数据,然后再重写的paint方法中直接获取使用。

             (1)  首先创建一个用来保存图形数据的shape类,新建数组对象。

	/**
	 * 创建图形对象时初始化该图形的数据
	 */
	public Shape(int x1, int y1, int x2, int y2, String name, Color color) {
		if (name.equals("直线") || name.equals("矩形") || name.equals("椭圆")) {
			this.x1 = x1;
			this.y1 = y1;
			this.x2 = x2;
			this.y2 = y2;
			this.name = name;
			this.color = color;
		} 
	}

}

               (2)在事件处理类DrawMouse中创建数组对象和数组角标index。每画出一个图形保存在数组中一次。由于点,三角形,多边形,曲线,橡皮擦,迭代图形都是通过两点绘制即drawline(),保存在直线重绘即可。

	private Shape[] shapeArray;
	private int index = 0;// 创建数组角标
	public void setShapeArray(Shape[] shapeArray) {//实例化数组
		this.shapeArray = shapeArray;
	}
		if (name.equals("直线")) {
			gr.drawLine(x1, y1, x2, y2);
			Shape shape = new Shape(x1, y1, x2, y2, "直线", gr.getColor());// 创建shape对象用来保存绘制图形的数据
			shapeArray[index] = shape;
			index++;
		}
		if (name.equals("矩形")) {
			gr.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
			Shape shape = new Shape(x1, y1, x2, y2, "矩形", gr.getColor());
			shapeArray[index] = shape;
			index++;
		}

                  (3)三角形和多边形的绘制是由多条直线绘制,所以每画出一条直线保存一次数据到数组中。

第一次点击的时候
        if (name.equals("三角形") && count == 1) {
			gr.drawLine(x1, y1, x2, y2);
			Shape shape = new Shape(x1, y1, x2, y2, "直线", gr.getColor());
			shapeArray[index] = shape;
			index++;
			count++;
		}
第二次点击的时候
		if (name.equals("三角形") && count == 2) {
			x3 = e.getX();
			y3 = e.getY();
			gr.drawLine(x2, y2, x3, y3);
			Shape shape = new Shape(x2, y2, x3, y3, "直线", gr.getColor());
			shapeArray[index] = shape;
			index++;
			if (e.getClickCount() == 2) {
				gr.drawLine(x1, y1, x3, y3);
				Shape shape1 = new Shape(x1, y1, x3, y3, "直线", gr.getColor());
				shapeArray[index] = shape1;
				index++;
				count = 1;
			}
		}

多边形count == 2(即第二次点击)或者双击闭合图形的时候

		if (name.equals("多边形") && count == 2) {
			x3 = e.getX();
			y3 = e.getY();
			gr.drawLine(x2, y2, x3, y3);
			Shape shape = new Shape(x2, y2, x3, y3, "直线", gr.getColor());
			shapeArray[index] = shape;
			index++;
			x2 = x3;
			y2 = y3;
			System.out.println("画一条线");
			if (e.getClickCount() == 2) {
				gr.drawLine(x1, y1, x3, y3);
				Shape shape1 = new Shape(x1, y1, x3, y3, "直线", gr.getColor());
				shapeArray[index] = shape1;
				index++;
				System.out.println("最后连接");
				count = 1;
			}
		}

                 (4)数据全部保存到数组中以后在界面类中继承JFrame或者JPanel,重写paint方法。

                   首先在界面类中调用事件处理类DrawMouse中的setShapeArray方法  ,将方法传递给界面类中的数组对象。

dr.setShapeArray(shapeArray);

                         super指父类中。this指本类中。

	// 绘制组件重写方法
	public void paint(Graphics gr) { 
		super.paint(gr);                     //调用父类中的方法
		System.out.println("重绘!");
		for (int i = 0; i < shapeArray.length; i++) {
			Shape shape = shapeArray[i];     //将数组赋值给shape对象
			if (shape != null) {             //如果数组不是空的
				shape.drawshape(gr);         //调用shape类中的方法drawshape
			} else {
				break;
			}
		}
	}
	// 取出shapeArray数组中保存的图形对象,绘制

                  (5)shape类中的重绘方法

	// 根据图形名字绘制对应的图形
	public void drawshape(Graphics gr) {
		switch (name) {
		case "直线":
			gr.setColor(color);
			gr.drawLine(x1, y1, x2, y2);
			break;
		case "矩形":
			gr.setColor(color);
			gr.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
			break;
		case "椭圆":
			gr.setColor(color);
			gr.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
			break;
		case"橡皮擦":
			gr.setColor(color);
			gr.fillRect(x1, y1, 50, 50);
			break;
		}
	}

 

你可能感兴趣的:(java)