1、大致思路:
- 画图板类Panel
要制作画图板的大致框架,首先需要一个画板(JPanel),然后是选择要画的图形、画笔的颜色、粗细以及后退、清除的按钮(JButton),最后将这个画板和所有按钮以流式布局的方式加到最终的大框架(JFrame)上,画图板的大致结构就完成了,主要需要用到的就是以上括号里的三个类。
需要注意的是,关于我自己写的这个画图板类Panel到底应该继承JFrame类还是继承JPanel类有两种想法:
1、继承JFrame,作为一个新型的框架类,在此类中编写显示界面的方法时再new一个JPanel类的画板加到this上,显示this。
2、继承JPanel,作为一个新型画板类,在此类中编写显示界面的方法时再new一个JFrame类的框架,将this加到这个框架上,显示这个框架。
个人觉得应该用第二种想法,因为到后面会涉及重写用于重绘的paint()函数,既然图形是画在画板JPanel上的,那么重绘也必然要针对画板JPanel,也就是说我要重写的是JPanel中的paint()函数,而不是JFrame中的,那么就只有继承JPanel,才能重写JPanel中的paint()函数,从而达到针对性重绘的目的。
在设置画图板显示之后,再利用Graphics graphics = this.getGraphics()在自己写的这个新型画板类的对象上获得画笔,并将画笔传到监听器类Listener中,在监听器中监听鼠标的各种行为并用此画笔画出对应的图形。注意:一定要在画图板设置可见之后再获得画笔,否则得到的画笔是空指针。
- 监听器类Listener
点击各按钮时,监听按钮点击事件需要用到ActionListener接口,画图时需要用到鼠标,因此也需要监听鼠标行为的相关监听器接口。使用时无论是定点位置监听鼠标行为的MouseListener,还是监听鼠标移动拖动的MouseMotionListener,还是两者兼而有之,都可以只用MouseAdapter来代替。MouseAdapter是一个类,其中含有MouseListener接口和MouseMotionListener接口的所有方法,所以继承了MouseAdapter类之后,不仅可以使用监听鼠标行为的所有常用方法,还不用像继承那两个接口那样必须把不用的方法也重写一遍,岂不美哉!
想清楚需要继承的接口与类之后,就要开始思考画每一个图形的每一步细节。画这个图形的每一步时,鼠标在这一刻的行为是什么?这个行为对应的是我需要重写的哪个函数?我在重写这个函数时,要在里面得到哪些坐标,还要做哪些其他的事以帮助完成整个图形的绘制?
- 画直线:按下——拖拽——释放。
1、首先要在画板上某个点按下鼠标(对应mousePressed(MouseEvent e){}函数),点击的同时在对应的行为函数中获得该点的坐标X1,Y1。
public void mousePressed(MouseEvent e){
if("直线".equals(shapename)){
x1 = e.getX(); y1 = e.getY(); //得到头点坐标
}
}
2、从这一点开始,用鼠标朝某一个方向进行拖拽,直到另一个点,然后释放鼠标(对应mouseReleased(MouseEvent e)函数),释放的同时在对应的行为函数中获取释放点的坐标X2,Y2,此时已经获得此线段的头坐标(X1,Y1)和(X2,Y2),调用画笔画直线的方法drawLine( X1, Y1, X2, Y2)即可画出一条直线。
public void mouseReleased(MouseEvent e){
if("直线".equals(shapename)){
x2 = e.getX(); y2 = e.getY(); //得到尾点坐标
graphics.drawLine(x1, y1, x2, y2); //连接头尾两点画直线
}
}
- 画三角形:画直线——点击(对应mouseClicked(MouseEvent e)函数)第三个点连接这条直线的首尾两点。
注意:由于点击 = 按下 + 释放,当鼠标点击时,监听器监听到鼠标行为的顺序依次是:按下——释放——点击,系统会先执行按下和释放所对应的的函数,最后再执行点击函数,因此为了使得点击的操作不受按下和释放的影响,在最后点击第三点画出三角形时,必须想办法避开前面的按下和释放操作,只执行点击操作,最简单的方法就是设置一个变量,画三角形时每完成一步,就让该变量+1,每次根据这个变量的大小来判断该进行哪一步,该避开哪一步,最后一个三角形画完后,使该变量回归初始值即可。
private int triangle = 1; //设置变量
public void mousePressed(MouseEvent e){
if("三角形".equals(shapename) && triangle==1){
x1 = e.getX(); y1 = e.getY();
triangle++; //执行完第一步,变量+1
}
}
public void mouseReleased(MouseEvent e){
if"三角形".equals(shapename) && triangle==2){ //如果变量为2的话才执行此操作
x2 = e.getX(); y2 = e.getY();
graphics.drawLine(x1, y1, x2, y2); //连接头尾两点画直线
triangle++; //执行完第二步,变量+1
}
}
public void mouseClicked(MouseEvent e){
if("三角形".equals(shapename) && triangle==3){ //如果变量为3的话才执行此操作
x = e.getX(); y = e.getY(); //得到第三点的坐标
graphics.drawLine(x, y, x1, y1);
graphics.drawLine(x, y, x2, y2); //连接第三点与已画直线的首尾两点形成三角形
triangle = 1; //三角形画完,变量回归初始值
}
}
- 画多边形:画直线——for(i=0;i<n;i++){点击某点,连接该点与上一直线的尾点形成新的直线}——双击某点(e.getClickCount()==2),