思路:
①画图板的界面
②创建监听器类
③给按钮加上鼠标监听
③画图版的重绘
第一部分:界面类
①画图板的界面 ③给按钮加上鼠标监听
public class SampleDraw extends JFrame {
public static void main(String[] args) {
SampleDraw sam = new SampleDraw();//创建该类对象
sam.showUI();//调用showUI方法
}
public void showUI() {
this.setSize(800, 600);//设置尺寸
this.setTitle("画板v1.0");//设置标题
this.setLocationRelativeTo(null);//设置居中
this.setDefaultCloseOperation(3);//设置关闭进程
FlowLayout flow = new FlowLayout();//布局方式为流式布局
this.setLayout(flow);
Color[] color = { Color.GREEN, Color.RED, Color.BLUE, Color.YELLOW };//创建一个数组保存颜色
DrawListener drawListener = new DrawListener();//新建监听器对象
for (int i = 0; i < color.length; i++) {//利用循环将颜色依次将赋给按钮的背景色
JButton jbu = new JButton();
jbu.setPreferredSize(new Dimension(30, 30));//设置按钮尺寸
jbu.setBackground(color[i]);//设置按钮的背景色
this.add(jbu);//把按钮加给窗体
jbu.addActionListener(drawListener);//给按钮添加监听器
}
String[] name = { "直线", "三角形", "正方形","矩形", "椭圆","棱形", "五边形", "图片1", "图片2", "画笔", "特殊三角形", "多边形" };////创建一个数组保存按钮名称
for (int i = 0; i < name.length; i++) {//利用循环将名字赋给按钮
JButton jbu1 = new JButton(name[i]);//创建按钮对象
this.add(jbu1);//把按钮对象加给窗体
jbu1.addActionListener(drawListener);//给按钮添加监听器
}
this.setVisible(true); //设置窗体可见
Graphics g = this.getGraphics();//创建画笔
this.addMouseListener(drawListener);//添加鼠标监听器
this.addMouseMotionListener(drawListener);//添加鼠标拖动监听器
drawListener.setGr(g);//调用监听器的set方法
drawListener.setShape(listshape);//调用监听器的setShape方法
}
}
第二部分:监听器类
②创建监听器
该类应该继承MouseListener, ActionListener, MouseMotionListener的接口
public class DrawListener implements MouseListener, ActionListener, MouseMotionListener {
private Graphics gr;//声明对象
private Color color;
private int flag = 1;
private String name;
private int x1, y1, x2, y2, x3, y3,x4,y4;
private ImageIcon icon = new ImageIcon("C:\\Users\\Administrator\\Pictures\\lu.jpg");//添加图片。注意路径为绝对路径,单斜杠变成双斜杠,加文件名和后缀格式
private ImageIcon icon2 = new ImageIcon("C:\\Users\\Administrator\\Pictures\\hua.jpg");
private ArrayList listshape;
public void setGr(Graphics g) {//传画笔
gr = g;
}
public void setShape(ArrayList listshape) {//传数组
this.listshape = listshape;
}
public void actionPerformed(ActionEvent e) {//监听方法
if ("".equals(e.getActionCommand())) {//如果按钮的文本内容为""
JButton jbu = (JButton) e.getSource();
color = jbu.getBackground();//获取按钮的背景色
gr.setColor(color);
} else {//按钮文本内容不为空
name = e.getActionCommand();//将按钮的文本内容赋给name
}
}
public void mouseDragged(MouseEvent e) {
x3 = e.getX();//x3 y3 为鼠标按压拖动时的坐标
y3 = e.getY();
if ("画笔".equals(name)) {//如果点击是“画笔”按钮
gr.drawLine(x1, y1, x3, y3);//画线
x1 = x3;
y1 = y3;
// 更新x1,y1的值,把每一个点依次相连。
}
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
x4 = e.getX();//将鼠标点击时的坐标赋给x4,y4
y4 = e.getY();
if ("特殊三角形".equals(name) && flag == 2) {//此时flag为2时,才能将点击的点和直线的两端链接起来
gr.drawLine(x1, y1, x4, y4);//画线
gr.drawLine(x2, y2, x4, y4);
flag = 1;//画完线后,将flag的值赋为1,这样能接着画第二个三角形
}
if ("多边形".equals(name) && flag == 2) {
gr.drawLine(x2, y2, x4, y4);
x2 = x4;
y2 = y4;
if (e.getClickCount() == 2) {//如果为双击
gr.drawLine(x1, y1, x4, y4);
flag = 1;
}
}
}
public void mousePressed(MouseEvent e) {
if (flag == 1) {
x1 = e.getX();
y1 = e.getY();
}
}
public void mouseReleased(MouseEvent e) {
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(x1 - x2), Math.abs(y1 - y2));
}
if ("椭圆".equals(name)) {
gr.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
if ("三角形".equals(name)) {
int[] xPoints = new int[] { x1, Math.abs((x1 + x2) / 2), x2 };
int[] yPoints = new int[] { y2, y1, y2 };
int nPoints = 3;
gr.drawPolygon(xPoints, yPoints, nPoints);
}
if ("图片1".equals(name)) {
gr.drawImage(icon.getImage(), Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2),
null);
}
if ("图片2".equals(name)) {
gr.drawImage(icon2.getImage(), Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2),
null);
}
if ("正方形".equals(name)) {
gr.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(x1 - x2));
}
if ("棱形".equals(name)) {
int[] xPoints = new int[] { (x1 + x2) / 2, x2, (x1 + x2) / 2, x1 };
int[] yPoints = new int[] { y2, (y1 + y2) / 2, y1, (y1 + y2) / 2 };
int nPoints = 4;
gr.drawPolygon(xPoints, yPoints, nPoints);
}
if ("五边形".equals(name)) {
int[] xPoints = new int[] { (x1 + x2) / 2, x2, x2 - (x2 - x1) / 4, x1 + (x2 - x1) / 4, x1 };
int[] yPoints = new int[] { y1, (y1 + y2) / 2, y2, y2, (y1 + y2) / 2 };
int nPoints = 5;
gr.drawPolygon(xPoints, yPoints, nPoints);
}
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) {
}
public void mouseExited(MouseEvent e) {
}
}
现在就实现了简单的画图版了,但是会有一个问题,当我们改变窗体的大小或者最小化窗体再打开来会发现,之前画的图都不见了。这是因为当窗体发生改变时,程序会重新从内存中获取更新后的数据绘制。我们没有将画过的形状存放到内存中,当窗体发生重绘的时候,就不会绘制了
第三步:画图板的重绘
定义一个Shape类。
其中定义一个队列,用于存放图形对象。(队列的大小随对象的增加而增加)
public class Shape {
private String name;
private Color color;
private int x1, x2, y1, y2 ;
private ImageIcon icon = new ImageIcon("C:\\Users\\Administrator\\Pictures\\lu.jpg");
private ImageIcon icon2 = new ImageIcon("C:\\Users\\Administrator\\Pictures\\hua.jpg");
public void setShape(int x1, int y1, int x2, int y2, String name, Color color) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.name = name;
this.color = color;
}
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(x1 - x2), Math.abs(y1 - y2));
break;
case "椭圆":
g.setColor(color);
g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
break;
case "三角形":
g.setColor(color);
int[] xPoints = new int[] { x1, Math.abs((x1 + x2) / 2), x2 };
int[] yPoints = new int[] { y2, y1, y2 };
int nPoints = 3;
g.drawPolygon(xPoints, yPoints, nPoints);
break;
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(x1 - x2), Math.abs(x1 - x2));
break;
case "五边形":
g.setColor(color);
int[] xPoints1 = new int[] { (x1 + x2) / 2, x2, x2 - (x2 - x1) / 4, x1 + (x2 - x1) / 4, x1 };
int[] yPoints1 = new int[] { y1, (y1 + y2) / 2, y2, y2, (y1 + y2) / 2 };
int nPoints1 = 5;
g.drawPolygon(xPoints1, yPoints1, nPoints1);
break;
case "棱形":
g.setColor(color);
int[] xPoints2 = new int[] { (x1 + x2) / 2, x2, (x1 + x2) / 2, x1 };
int[] yPoints2 = new int[] { y2, (y1 + y2) / 2, y1, (y1 + y2) / 2 };
int nPoints2 = 4;
g.drawPolygon(xPoints2, yPoints2, nPoints2);
break;
case "特殊三角形":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
break;
case "多边形":
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
break;
case"图片1":
g.setColor(color);
g.drawImage(icon.getImage(), x1,y1,x2,y2,null);
break;
case"图片2":
g.setColor(color);
g.drawImage(icon2.getImage(), x1,y1,x2,y2,null);
break;
}
}
}
再在监听器类中,画一个图形就将图形存入Shape类中的队列中去。例如:
if ("直线".equals(name)) {
gr.drawLine(x1, y1, x2, y2);
Shape shape = new Shape();
shape.setShape(x1, y1, x2, y2, name, color);
listshape.add(shape) ;
}
最后在主界面的类中去定义重绘的方法和调用。在重绘方法中将队列中的对象取出来,调用画的方法
public void paint(Graphics g) {//重绘方法
super.paint(g);
//进行重绘
for (int i = 0; i < listshape.size(); i++) {
Shape shape = listshape.get(i);//依次取出对象
if (shape != null) {
shape.drawShape(g);//调用对象的画的方法
} else {
break;
}
}
}
图形的重绘就到这里啦!