一.首先介绍下画图板需要做到什么程度,就是在一个界面上我们能通过点击按钮来画出一些简单的图形,能选择颜色。具体见图- -
那么首先我们需要一个窗体来进行绘画,创建窗体我们需要JFrame类,具体代码如下,
public void showUI() {
// 创建一个界面
// 设置界面标题
JFrame jf=new JFrame();
jf.setTitle("简易画图板");
// 设置界面大小
jf.setSize(600, 400);
jf.setLocationRelativeTo(null);
// 关闭时退出程序
jf.setDefaultCloseOperation(3);
jf.setLayout(new FlowLayout());
jf.add(this);
// 设置可见,放最后面
jf.setVisible(true);
}
之后按钮的添加就不用详细贴代码了,这里我为了不让画笔影响到按钮,加了个Jpanel组件,让画板界面类继承JPanel类,之后利用this关键字获取画笔就行了,按钮放在界面上和Jpanel分开,之后再Jpanel上获取画笔,就能在画画的时候不干扰到按钮了。这里注意获得画笔一定要在窗体可见之后。
// 添加画笔对象
Graphics g = this.getGraphics();
写到这里,那么准备工作就差不多了。那么怎样实现功能呢,通俗就是让我们点击一个按钮,计算机就知道我们要干什么呢,这里就需要用到事件监听机制,首先说下事件监听机制的用法,第一步是要确定事件源,通俗说就是哪个组件发生了事件,那么哪个组件就是事件源对象,第二步是创建监听器对象(dl),最后就是把监听器对象加到事件源上,这样我们的步骤就有了,但是这里需要注意的是事件监听类都是接口类,我们要用到事件监听类那么就必须得新建个类(Drawlistener)来继承接口类,注意一定要重写接口中的所有方法,这样才能使用其中的方法。我们要监听哪个组件就用加上相应的监听器。
那么接下来我们需要在新建类中用到我们已经创建好的画笔对象,那么就需要传参。传参的话,我们首先需要在新建类中利用Set方法用来保存传过来的数据。具体代码如下:
在画板界面类中创建Drawlistener的对象,然后调用add方法给组件加上监听器
// 创建鼠标监听器对象,把画布对象传给监听器
Drawlistener dl = new Drawlistener();
this.addMouseListener(dl);
this.addMouseMotionListener(dl);
利用set方法传参,在监听器类中写set方法,然后在画板界面类中调用set方法就OK了。
private Graphics gr;
public void setGr(Graphics g) {
gr = g;
}
然后接下来我们就可以画图形了,那要怎么画图形呢,这里我们知道图形可以通过鼠标拖动,按下,点击之类的动作来完成,那我们只需要记录下完成这些动作是的坐标,再通过Graphics类中的画线方法,就可以完成我们的绘画了。这里重点说下多边形的画法,效果呢就是先画一条线,然后鼠标每点击一次那么就自动画一条线,鼠标点击2次则画完最后一条线完成一个封闭的图形,这里多边形我们知道先画一条线,可是这里画完线之后再点击一次的话,就会覆盖我们之前按下和释放的点的坐标,所以这个时候我们需要加一个判断,之后可以把第一次划线的最后一个点的坐标当成下一次划线的起始点坐标,然后我们可以获得鼠标点击的次数从而控制最后一条线的实现。具体代码如下:
public void mouseClicked(MouseEvent e) {
System.out.printf("点击");
x3 = e.getX();
y3 = e.getY();
if ("三角形".equals(name) && flag == 2 ) {
gr.drawLine(x1, y1, x3, y3);
gr.drawLine(x3, y3, x2, y2);
flag=1;
}
if("多边形".equals(name)&&flag==2){
gr.drawLine(x2, y2, x3, y3);
x2=x3;
y2=y3;
if(e.getClickCount()==2){
gr.drawLine(x1, y1, x3, y3);
}
}
}
public void mousePressed(MouseEvent e) {
System.out.printf("按下");
if(flag == 1){
x1 = e.getX();
y1 = e.getY();
}
}
public void mouseReleased(MouseEvent e) {
System.out.print("释放");
if(flag == 1){
x2 = e.getX();
y2 = e.getY();
}
if ("直线".equals(name)) {
gr.drawLine(x1, y1, x2, y2);
}
if ("矩形".equals(name)) {
gr.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
}
if ("三角形".equals(name) && flag == 1) {
gr.drawLine(x1, y1, x2, y2);
flag++;
}
if("多边形".equals(name) && flag == 1){
gr.drawLine(x1, y1, x2, y2);
flag++;
}
};
public void mouseEntered(MouseEvent e) {
System.out.print("进入");
};
public void mouseExited(MouseEvent e) {
System.out.print("退出");
};
public void actionPerformed(ActionEvent e) {
if ("".equals(e.getActionCommand())) {
// 获取当前事件源对象
JButton jbu = (JButton) e.getSource();
// 获取按钮的背景色
Color color = jbu.getBackground();
gr.setColor(color);
}else{
name = e.getActionCommand();
//System.out.print("name=" + name);
}
}
到了这里我们的画图板也就基本成型了。
二.画图板的重绘
细心的小朋友可以发现我们画好图形之后只要变动窗体的大小或者隐藏窗体,那么我们之前画好的图形就会消失不见,这是因为程序中自带了一种重绘组件的方法,只要窗体发生了改变,那么就会进行重绘。那么接下来我们需要做的就是在程序重绘组件的同时把我们之前画的图形也给画出来,这样就能解决问题了,首先我们应该重写个类来写我们重画图形的方法,之后利用数组保存我们我们第一次画图时图形的数据,然后重写系统绘画的方法(Paint),方法重写当然需要用到继承了,系统重绘哪个组件我们就继承哪个组件,然后系统重绘哪个组件的时候就会把我们原来的图形画出来了。这里为了方便,小编新建了图形类把之前画的所有图形都看成是对象,这里就直接贴代码了。
public class Shape {
private int x1,y1,x2,y2,x3,y3;
private String name;
private Color color;
private Stroke stroke;
/**
* 初始化该图形对象的数据
* @param x1
* @param y1
* @param x2
* @param y2
* @param name
*/
public Shape(int x1,int y1,int x2,int y2,int x3,int y3,String name,Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.name = name;
this.color=color;
}
public Shape(int x1,int y1,int x2,int y2,String name,Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.name = name;
this.color=color;
}
public Shape(int x1,int y1,int x2,int y2,String name,Color color,Stroke stroke){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.name = name;
this.color=color;
this.stroke=stroke;
}
/**
* 画图形的方法
* @param g
*/
public void drawShape(Graphics g){
switch(name){
case "直线":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
break;
case "矩形":
g.setColor(color);
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
break;
case"三角形":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
g.drawLine(x1, y1, x3, y3);
g.drawLine(x3, y3, x2, y2);
break;
case"多边形":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
break;
case"曲线":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
break;
case"橡皮檫":
g.setColor(color);
Graphics2D g2=(Graphics2D)g;
g2.setStroke(stroke);
g.drawLine(x1, y1, x2, y2);
break;
}
}
}
这样一个简单的画图板就完成了。
三.遇到的问题及总结
1.首先是获取画笔一定要在窗体可见之后,不然是没效果的。
2.发现画的时候会影响到按钮,之后通过加JPanel容器解决。
3.万物皆可看作对象。