上篇博客中介绍了界面的实现方法,在这篇博客中将对每个按钮的功能的实现进行讲解并介绍重绘

首先肯定要添加事件监听机制了,那么问题来了,事件源对象是谁?需要添加什么方法?事件接口是什么?

1、我们需要点击按钮,获取按钮上的文字信息,颜色信息,粗细信息。那么,此时事件源对象就是按钮,监听方法就是addActionListener(ActionListener e),事件接口就是ActionListener

2、要根据在窗体上按下和释放的位置画一个图形,此时事件源对象就是窗体,监听方法就是addMouseListener(MouseListener e),事件接口就是MouseListener

 public class DrawListener extends MouseAdapter implements ActionListener {

     private Color color = Color.black;// 声明颜色属性,存储用户选择的颜色
private int width = 1;// 声明粗细属性,存储用户选择的粗细
private String type = "Line";// 声明图形属性,存储用户选择的图形
private int x1, y1, x2, y2, x3 = 0, y3 = 0, x4 = 0, y4 = 0, x5, y5;// 声明坐标值属性,存储鼠标按下和释放的坐标值
private Graphics2D g;// 声明画笔类属性,组件是画出来的,现在要在组件上画图形,Graphics从组件上获取
private DrawMain dm;// 声明画图程序窗体组件属性
private JTextField text;// 获取文本框内容
private double H = 100;// 等腰三角形的高度
private int num = 0;
private List<Shape> list;
private ImageIcon i = new ImageIcon("C:\\Users\\long452a\\Desktop\\a1.jpg"); /**
* 构造方法
*
* @param dm画图程序的窗体组件对象
*/
public DrawListener(DrawMain dm, JTextField text, List<Shape> list) {
this.dm = dm;
this.text = text;
this.list = list;
} /**
* 点击按钮时执行的事件处理方法
*
* @param e对象中存储了事件源对象的信息和动作信息
*/
public void actionPerformed(ActionEvent e) {
} /**
* Invoked when the mouse button has been clicked (pressed and released) on a
* component.
*/
public void mouseClicked(MouseEvent e) {
} /**
* Invoked when a mouse button has been pressed on a component.
*/
public void mousePressed(MouseEvent e) {
} /**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(MouseEvent e) {
} public void mouseDragged(MouseEvent e) {
}
}

这样我们的类就建好了,下面就该写里面的方法了

     /**
* 点击按钮时执行的事件处理方法
*
* @param e对象中存储了事件源对象的信息和动作信息
*/
public void actionPerformed(ActionEvent e) {
String text = e.getActionCommand();
if (text.equals("")) {
JButton button = (JButton) e.getSource();
color = button.getBackground();
} else if (text.equals("1") || text.equals("3") || text.equals("5")) {
width = Integer.parseInt(text);
} else {
type = text;
}
// System.out.println(color + ">>" + width + ">>" + type);
} /**
* Invoked when the mouse button has been clicked (pressed and released) on a
* component.
*/
public void mouseClicked(MouseEvent e) {
x4 = x2;
y4 = y2;
} /**
* Invoked when a mouse button has been pressed on a component.
*/
public void mousePressed(MouseEvent e) {
x1 = e.getX() + 7;
y1 = e.getY() + 183;
if (y1 < 183)
y1 = 183;
g = (Graphics2D) dm.getGraphics();// 从窗体上获取画笔对象
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 设置画笔抗锯齿
g.setColor(color);// 设置画笔颜色
g.setStroke(new BasicStroke(width));// 设置画笔线条粗细 } /**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(MouseEvent e) {
x2 = e.getX() + 7;
y2 = e.getY() + 183;
if (y2 < 183)
y2 = 183;
if (type.equals("iso_Tri")) {
if (x1 == x2) {
g.drawLine(x1, y1, x2, y2);
g.drawLine(x1, y1, x1 + (int) H, (y2 + y1) / 2);
g.drawLine(x2, y2, x1 + (int) H, (y2 + y1) / 2);
list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
list.add(new Shape(x1, y1, x1 + (int) H, (y2 + y1) / 2, width, color, type, i, dm, text));
list.add(new Shape(x2, y2, x1 + (int) H, (y2 + y1) / 2, width, color, type, i, dm, text));
} else if (y1 == y2) {
g.drawLine(x1, y1, x2, y2);
g.drawLine(x1, y1, (x1 + x2) / 2, y1 + (int) H);
g.drawLine(x2, y2, (x1 + x2) / 2, y1 + (int) H);
list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
list.add(new Shape(x1, y1, x1 + (x1 + x2) / 2, y1 + (int) H, width, color, type, i, dm, text));
list.add(new Shape(x2, y2, x1 + (x1 + x2) / 2, y1 + (int) H, width, color, type, i, dm, text));
} else {
double a = Math.atan((double) (x2 - x1) / (double) (y2 - y1));
double x3 = (double) (x1 + x2) / 2 + H * Math.cos(a);
double y3 = (double) (y1 + y2) / 2 - H * Math.sin(a);
g.drawLine(x1, y1, x2, y2);
g.drawLine(x1, y1, (int) x3, (int) y3);
g.drawLine(x2, y2, (int) x3, (int) y3);
list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
list.add(new Shape(x1, y1, x1 + (int) x3, (int) y3, width, color, type, i, dm, text));
list.add(new Shape(x2, y2, (int) x3, (int) y3, width, color, type, i, dm, text));
}
} else if (type.equals("Polygon")) {
if (num == 0) {
g.drawLine(x1, y1, x2, y2);
list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
x5 = x2;
y5 = y2;
}
num++;
if (num == 1) {
x3 = x1;
y3 = y1;
}
if (x2 == x4 && y2 == y4) {
g.drawLine(x1, y1, x3, y3);
list.add(new Shape(x1, y1, x3, y3, width, color, type, i, dm, text));
num = 0;
} else {
g.drawLine(x2, y2, x5, y5);
list.add(new Shape(x2, y2, x5, y5, width, color, type, i, dm, text));
x5 = x2;
y5 = y2;
}
} else {
Shape s = new Shape(x1, y1, x2, y2, width, color, type, i, dm, text);
s.draw(g);
list.add(s);
}
} public void mouseDragged(MouseEvent e) {
if (type.equals("Pencil")) {
x2 = e.getX() + 7;//这里的+7 +183 是调出来的,能够使画的图是沿着鼠标
y2 = e.getY() + 183;
if (y2 < 183)
y2 = 183;
Shape s = new Shape(x1, y1, x2, y2, width, color, type, i, dm, text);
s.draw(g);
list.add(s);
x1 = x2;
y1 = y2;
} else if (type.equals("Erase")) {
x2 = e.getX() + 7;
y2 = e.getY() + 183;
if (y2 < 183)
y2 = 183;
Shape s = new Shape(x1, y1, x2, y2, width, Color.WHITE, type, i, dm, text);
s.draw(g);
list.add(s);
x1 = x2;
y1 = y2;
} else if (type.equals("喷枪")) // 难点
{
Random rand = new Random();// 实例化一个随机数类的对象
int size = rand.nextInt(50);// 随机决定要画的点数
x2 = e.getX() + 7;
y2 = e.getY() + 183;
for (int j = 0; j < size; j++) {
// 在0-7之间可以取50次
int x = rand.nextInt(10);
int y = rand.nextInt(10);
// 不断改变(x1,y1)的坐标值,实现在(x1,y1)的周围画点
Shape s = new Shape(x2 + x, y2 + y, x2 + x, y2 + y, width, color, type, i, dm, text);
s.draw(g);
list.add(s);
x1 = x2;
y1 = y2;
}
}
}

  仔细看看代码,你也许注意到了,我在画图时创建了一个Shape对象,并且还把Shape对象存到了一个List中,为什么要这么做?你们可以去别人的博客上贴一个粗略实现的画图板代码,画几条直线然后再改变窗体的大小试试看,是不是画的直线不见了?那要怎么做才能使这些图形保存下来呢?这就需要用到重绘了。

  但是,我们需要知道,为什么图形会消失?其实计算机中的界面什么都是画出来的。自然组件也是画出来的,而改变组件大小的时候,原来的组件无法满足现在组件的显示要求,所以组件要重新画一次,然而此时组件上的图形并不会重新再画一次,为什么?组件已经默认有重绘的方法了paint(Graphics g),所以我们需要重写这个方法,但是我们怎么能让计算机知道之前画了什么呢?这是就需要把每次画的内容记录到队列或数组中,重绘时就可以根据这个队列或是数组进行了。而创建Shape对象自然是为了方便保存这些图形的数据了。

下面是Shape的写法

 public class Shape {

     private int x1, y1, x2, y2, width;
private Color color;
private String type;
private ImageIcon i;
private DrawMain dm;
private JTextField text; public Shape(int x1, int y1, int x2, int y2, int width, Color color, String type, ImageIcon i, DrawMain dm,
JTextField text) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.width = width;
this.color = color;
this.type = type;
this.i = i;
this.dm = dm;
this.text = text;
} public void draw(Graphics2D g) {
g.setColor(color);
g.setStroke(new BasicStroke(width));
if (type.equals("Line") || type.equals("Pencil") || type.equals("iso_Tri") || type.equals("Polygon")
|| type.equals("Erase") || type.equals("喷枪")) {
g.drawLine(x1, y1, x2, y2);
} else if (type.equals("Oval")) {
g.fillOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
} else if (type.equals("Rect")) {
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
} else if (type.equals("RoundRect")) {
g.drawRoundRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1),
Math.abs(x2 - x1) / 3, Math.abs(y2 - y1) / 3);
} else if (type.equals("fill3DRect")) {
g.fill3DRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1), true);
} else if (type.equals("fillArc")) {
double r = ((x2 - x1) * (x2 - x1) + y1 * y1) / (2 * y1);
double m = Math.asin((double) (x2 - x1) / r);
g.fillArc(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), (int) r, 0, (int) (m * 180 / Math.PI));
} else if (type.equals("Image")) {
g.drawImage(i.getImage(), Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1), dm);
} else if (type.equals("Text")) {
g.drawString(text.getText(), x1, y1);
}
} }

现在还有一个问题,paint该写在哪?写在之前写的DrawMain中

private List<Shape> list = new ArrayList<Shape>();

    public void paint(Graphics gr) {
super.paint(gr);
Graphics2D g = (Graphics2D) gr;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int i = 0; i < list.size(); i++) {
Shape shape = list.get(i);
shape.draw(g);
}
}

提醒一下:别忘了把事件监听添加到组件中!!!!

这样一来,我们的画图板就能完美使用了。当然这个画图板跟系统中的比起来还是差了很多了,比如撤销、重做、保存等功能都还不具备,剩下的功能就需要后面慢慢研究再完善了。

JAVA 画图板实现(基本画图功能+界面UI)二、功能实现及重绘实现的更多相关文章

  1. 很值得学习的java 画图板源码

    很值得学习的java 画图板源码下载地址:http://download.csdn.net/source/2371150 package minidrawpad; import java.awt.*; ...

  2. JAVA 画图板实现(基本画图功能+界面UI)一、界面实现

    /*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 1978702969@qq.com*/ 这段时间在学JAVA的swing界面开发,试着做了个画图板.实现了直线.曲线.喷枪.矩形.圆形.文字 ...

  3. Java版简易画图板的实现

    Windows的画图板相信很多人都用过,这次我们就来讲讲Java版本的简易画板的实现. 基本的思路是这样的:画板实现大致分三部分:一是画板界面的实现,二是画板的监听以及画图的实现,三是画板的重绘.(文 ...

  4. Java编写画图板程序细节-保存已画图形

    没有Java编写画图板程序细节-保存已画图形   一.为何我们要保存画图板上已画图形呢? 有很多人会问,为什么我们一定要保存画图板上已经画好了的图形呢?原因很简单.当我们在画图板上画完自己想画的图形后 ...

  5. iOS开发之画图板(贝塞尔曲线)

    贝塞尔曲线,听着挺牛气一词,不过下面我们在做画图板的时候就用到贝塞尔绘直线,没用到绘制曲线的功能.如果会点PS的小伙伴会对贝塞尔曲线有更直观的理解.这篇博文的重点不在于如何用使用贝塞尔曲线,而是利用贝 ...

  6. Robot Framework使用Phantomjs进行无界面UI自动化测试

    Robot Framework 是一款关键字驱动的验收自动化测试框架,现在在国内使用的越来越广泛了.一种通用的Web UI自动化测试解决方案是Robot Framework+Selenium2Libr ...

  7. Java 从零开始实现一个画图板、以及图像处理功能,代码可复现

    Java 从零开始实现一个画图板.以及图像处理功能,代码可复现 这是一个学习分享博客,带你从零开始实现一个画图板.图像处理的小项目,为了降低阅读难度,本博客将画图板的一步步迭代优化过程展示给读者,篇幅 ...

  8. 【示例代码】HTML+JS 画图板源码分享

    一个有趣的画图板, 用了 HTML5中的本地存储.下载.canvas 等技术,这个项目中用到了canvas 的很多基础功能,初学者可以学习一下 . 建议开发童鞋使用统一开发环境UDE来进行查看.调试. ...

  9. wxPython 画图板

    终于开始Python学习之旅了,姑且以一个“画图板”小项目开始吧.放慢脚步,一点一点地学习. 1月28日更新 第一次遇到的麻烦便是“重绘”,查了好多资料,终于重绘成功了. #-*- encoding: ...

随机推荐

  1. ES6学习(二)基础命令

    一.Let 和 const  作用域的概念:在es5之前是有两个作用域,一个是全局作用域,另外一个是函数作用域,在es6中就多了这样一个块作用域.在这里let 和 const 就是传说中的块作用域,它 ...

  2. 【leetcode】Path Sum2

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  3. SQL Server 数据库对象命名参考

    一. 引言 编码规范是一个优秀程序员的必备素质,然而,有很多人非常注重程序中变量.方法.类的命名,却忽视了同样重要的数据库对象命名.这篇文章结合许多技术文章和资料,以及我自己的开发经验,对数据库对象的 ...

  4. Kubernetes HPA

    简介 通过手工执行 kubectl scale 命令或者通过修改deployment的replicas数量,可以实现 Pod 扩容或缩容.但如果仅止于此,显然不符合 Google 对 Kubernet ...

  5. Python 发射导弹的正确方式

    ——此文以纪念南京大屠杀79周年 今天Toby教你如何用python的basemap包绘制轰炸东京的地图. 在数据可视化过程中,我们常常需要将数据根据其采集的地理位置在地图上显示出来.比如说我们会想要 ...

  6. Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer)

    Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.映射字节缓冲区 1>.什么是虚拟内存 答:虚拟内 ...

  7. openstack项目【day23】:虚拟化介绍

    本节内容 一 什么是虚拟化 二 为何要学习虚拟化 三 虚拟化技术主要分类(了解) 四 平台虚拟化技术又可以细分(了解) 一 什么是虚拟化 虚拟化说白了就是本来是一个完整的资源,切分或者说虚拟成多份,让 ...

  8. Sql语句里面调用变量

    sql语句里面调用变量的话有两种情况,一种是字符类型,一种是整型.浮点型之类的数字 db1.Execute("insert DataInformation values('" + ...

  9. python创建与遍历List二维列表

    python创建与遍历List二维列表 觉得有用的话,欢迎一起讨论相互学习~Follow Me python 创建List二维列表 lists = [[] for i in range(3)] # 创 ...

  10. ifconfig不显示网卡eth0

    参考资料:http://blog.itpub.net/25851087/viewspace-1700568/ 在/etc/sysconfig/network-script/ifcfg-eth0网卡配置 ...