drawDrawListener里面只写了画直线和曲线的方法,读者可以根据自己的需求添加,思路和方式都是一样的。Draw类里面有些需要注意的地方在这里提一下:一个是画笔g的获取一定要在窗体的可见之后采取获取,不然获取的画笔对象返回值会是null。二是要为图形按钮添加监听,DrawListener的实例化需要在setVisible方法之前,所以不建议使用构造方法直接传入g画笔参数,我使用的是set方法。最后是注意一下使用哪个添加方法,按钮使用的是addActionListener方法,画板面板使用的是addMouseListener和addMouseMotionListener方法。使用画板面板来获取画笔并给画面面板添加监听是为了让绘图的时候图形不会跑出面板外,这里的画笔和监听都由主窗体获得也是可以的,不过绘制时会出现线画出面板的问题。

画板的重绘:

到这里画板的制作已经基本实现了,我们已经可以在上面绘制各种各样的图形了。但是细心的人可能会发现一个问题,那就是如果把窗体最小化之后再次打开,画板上原本已经画好的东西会全部都消失了。这样子肯定是不行的,辛辛苦苦画的“大作”怎么能说说没就没了呢。那么为什么会出现这样的问题呢?要回答这个问题我们就需要先了解Java的绘图机制。做画图板我们使用的是Swing组件,这套组件是基于原先的AWT组件开发,在绘制的时候会调用系统的画图函数,这就是为什么我们可以从面板或者是窗体中获取画笔对象的原因。这也就是说Java中你所能够看到窗体,按钮或者其它的所有组件其实都是画出来。所以当我们点击窗体使它最小化或者改变大小的时候,原来的画的窗体就不能适应需要了,这时系统会调用JFrame的paint方法实现窗体的重绘,也就是再次画了一个新的窗体,而JFrame的paint方法只对窗体已经添加的组件有效,我们自己绘制的东西并没有写在paint方法里面,所以窗体重绘之后,我们原先绘制的图形也就消失了。要解决这个问题我们需要重写父类的paint方法。但是这样的话问题又来了,画图是在DrawListener类里面实现的,要怎么把它们弄到paint方法里面去呢?

当然方法可能有很多,这里我只介绍我所知道的:要把画出来的图形在paint方法中再次画出来,就需要有东西来保存画过的图形。保存可以使用数组或者集合,这里推荐使用集合,可以很方便的实现添加,而不需要去考虑大小的问题。数组的实现也大同小异,这里就不多做介绍。确定了使用集合,那么集合内保存什么类型的数据呢?毫无疑问应该保存的是图形的数据,但是集合使用泛型的话也只能保存同一种类型的数据,我们却有那么多种图形?这里就可以使用接口或者抽象类,我们只需要创建不同得图形类,让它继承抽象类或者是实现接口。然后每画一个图形就实例化一个图形的对象,存入集合中,最后在paint方法中遍历集合,重新绘制图形即可。

下面直接贴最终代码(仍然只写了直线和曲线),只是添加了几行代码,注意与前面比较。

//图形接口package Cbs;//图形集合public interface NetJavaShape {public abstract void draw();

}//直线类package Cbs;import java.awt.Color;import java.awt.Graphics;import Cbs.NetJavaShape;public class ImpLine implements NetJavaShape{

Graphics g;int x1, y1,x2, y2;

Color c;public ImpLine(Graphics g,int x1,int y1,int x2,int y2,Color c){this.g=g;this.c=c;this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;

}public void draw() {

g.setColor(c);

g.drawLine(x1, y1, x2, y2);

}

}//DrawListener类package Cbs;import java.awt.Color;import java.awt.Graphics;import java.util.List;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.util.ArrayList;import Cbs.NetJavaShape;import javax.swing.JButton;public class DrawListener implements ActionListener, MouseListener,

MouseMotionListener {private Color color=Color.BLACK;//颜色属性,初始值为黑色private Graphics g;//画笔属性private String str;//保存按钮上的字符串,区分不同的按钮private int x1,y1,x2,y2;//(x1,y1),(x2,y2)分别为鼠标的按下和释放时的坐标private JButton nowColor;//当前颜色按钮//保存图形对象的集合private List shapesArray = new ArrayList();//图形private NetJavaShape shape;//在draw类中获取集合public List getShapesArray() {return shapesArray;

}//获取Draw类的画笔对象public void setG(Graphics g) {this.g = g;

}//获取当前颜色按钮public void setNowColor(JButton nowColor) {this.nowColor = nowColor;

}

@Override//鼠标拖动的方法public void mouseDragged(MouseEvent e) {//画曲线的方法if ("画曲线".equals(str)) {int x, y;

x = e.getX();

y = e.getY();//实例化对象,曲线也是直线画的所以不同新建一个曲线类了shape=new ImpLine(g,x,y,x1,y1,color);//调用画图方法 shape.draw();//将图形存入集合中 shapesArray.add(shape);// g.drawLine(x, y, x1, y1);x1 = x;

y1 = y;

}

}

@Override//鼠标移动方法public void mouseMoved(MouseEvent e) {

}

@Override//鼠标单击方法public void mouseClicked(MouseEvent e) {

}

@Override//鼠标按下方法public void mousePressed(MouseEvent e) {

g.setColor(color);//改变画笔的颜色

x1=e.getX();//获取按下时鼠标的x坐标y1=e.getY();//获取按下时鼠标的y坐标 }

@Override//鼠标释放方法public void mouseReleased(MouseEvent e) {

x2=e.getX();//获取释放时鼠标的x坐标y2=e.getY();//获取释放时鼠标的y坐标//画直线的方法if ("画直线".equals(str)) {//实例化对象,shape=new ImpLine(g,x1,y1,x2,y2,color);//调用画图方法 shape.draw();//将图形存入集合中 shapesArray.add(shape);// g.drawLine(x1, y1, x2, y2); }

}

@Override//鼠标进入方法public void mouseEntered(MouseEvent e) {

}

@Override//鼠标退出方法public void mouseExited(MouseEvent e) {

}

@Override//处理按钮上的鼠标点击动作public void actionPerformed(ActionEvent e) { if ("".equals(e.getActionCommand())) {

JButton jb = (JButton) e.getSource();

color = jb.getBackground();

nowColor.setBackground(color);//处理当前颜色} else {

str = e.getActionCommand();

}

}

}//draw类package Cbs;import java.awt.Color;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.Graphics;import java.awt.GridLayout;import java.util.ArrayList;import java.util.List;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;/**

* Draw类,用于界面的初始化

* @author CBS */@SuppressWarnings("serial")public class Draw extends JFrame {private DrawListener dl;private Graphics g;//保存图形对象的集合private List shapesArray = new ArrayList();// 界面初始化方法public void showUI() {

setTitle("画图");//窗体名称setSize(1200, 900);//窗体大小setDefaultCloseOperation(3);

setLocationRelativeTo(null);//窗体居中FlowLayout layout = new FlowLayout(FlowLayout.LEFT);//流式布局左对齐setLayout(layout);//窗体使用流式布局管理器this.setResizable(false);//窗体大小不变 //使用数组保存按钮名String buttonName[] = { "画直线", "画椭圆", "画曲线", "多边形", "橡皮擦", "拖动线","三角形", "画球形", "笔刷", "喷枪", "色子", "立体矩形", "立体圆", "立体三角","迭代分形", "现代分形", "枫叶", "画树", "mandelbrot集", "L-System", "迭代画线","迭代三角形", "谢尔宾斯基地毯", "画字符", "清空","吸管" ,"矩形","五角星","多线","字符"};

JPanel jp1=new JPanel(new GridLayout(15, 2,10,10));//用于保存图形按钮,使用网格布局jp1.setPreferredSize(new Dimension(200, 800)); //实例化DrawListener对象dl=new DrawListener();//循环为按钮面板添加按钮for (int i = 0; i < buttonName.length; i++) {

JButton jbutton = new JButton(buttonName[i]);

jbutton.addActionListener(dl);//为按钮添加监听 jp1.add(jbutton);

}

JPanel jp2=new JPanel();//画布面板jp2.setPreferredSize(new Dimension(970, 800));

jp2.setBackground(Color.WHITE); // 定义Color数组,用来存储按钮上要显示的颜色信息Color[] colorArray = { Color.BLUE, Color.GREEN, Color.RED, Color.BLACK,Color.ORANGE,Color.PINK,Color.CYAN,Color.MAGENTA,Color.DARK_GRAY,Color.GRAY,Color.LIGHT_GRAY,Color.YELLOW};//用于保存颜色按钮的面板JPanel jp3=new JPanel(new GridLayout(1,colorArray.length,3,3));// 循环遍历colorArray数组,根据数组中的元素来实例化按钮对象for (int i = 0; i < colorArray.length; i++) {

JButton button = new JButton();

button.setBackground(colorArray[i]);

button.setPreferredSize(new Dimension(30, 30));

button.addActionListener(dl);//为按钮添加监听 jp3.add(button);

}//将面板添加到主窗体this.add(jp1);this.add(jp2);this.add(jp3);//添加按钮,作为当前颜色JButton nowColor=new JButton();

nowColor.setPreferredSize(new Dimension(40,40));

nowColor.setBackground(Color.BLACK);//默认黑色 add(nowColor);//设置窗体的组件可见,如果为FALSE就看不到任何组件setVisible(true); //获取画笔对象g=jp2.getGraphics();

dl.setG(g);

dl.setNowColor(nowColor);//获取保存的集合shapesArray=dl.getShapesArray();//为面板添加鼠标监听,用于绘制图形 jp2.addMouseListener(dl);

jp2.addMouseMotionListener(dl);

}

@Override//重写paint方法public void paint(Graphics g) {//调用父类的paint方法,绘制界面上的组件super.paint(g);//foreach遍历集合for (NetJavaShape l : shapesArray) {

l.draw();

}

}

}View Code

这里使用集合添加图形实现画板的重绘时,我是每实现一个图形就会新建一个类来保存图形的信息,这样图形类就会有很多。如果不想创建那么多的图形类可以把它们都放到一个类里面,设置一个type的参数,赋上按钮的名称。然后在draw方法中依据这个值判断是什么图形实现不同的画图方法。这样画板的所有功能基本就实现了,画板的项目也就到这里。

总结:

画图板的制作重要用到了Swing的组件,事件监听机制,Graphics绘图和画板的重绘以及集合的使用,抽象类或者是接口作为规范图形类的作用。

监听器类

package com.baidu;

import java.awt.*;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

public class MyMouseListener implements MouseListener{

//颜色

Panel p;

//画布

Graphics g;

//动作命令

private SimpleDraw draw;

//给出坐标

private int x1,y1,x2,y2;

//构造方法

public MyMouseListener(SimpleDraw draw){

this.g=draw.getGraphics();//将传过来的对象值赋给属性g

this.draw=draw;

}

//鼠标进入到组件上时调用

@Override

public void mouseClicked(MouseEvent e) {

}

//鼠标离开组件时调用

@Override

public void mouseEntered(MouseEvent e) {

}

@Override

public void mouseExited(MouseEvent e) {

}

@Override

public void mousePressed(MouseEvent e) {

x1=e.getX();

y1=e.getY();

}

@Override

public void mouseReleased(MouseEvent e) {

x2=e.getX();

y2=e.getY();

String command = draw.getCommand();

g.setColor(Color.blue);

if(command.equals("直线")){

g.drawLine(x1, y1, x2, y2);

}else if(command.equals("矩形")){

g.drawRect(x1, y1, x2-x1, y2-y1);

}else if(command.equals("椭圆")){

g.drawOval(x1, y1, x2-x1, y2-y1);

}

}

}

java画板教程_使用Java制作简易的画板教程相关推荐

  1. java核心教程_核心Java教程

    java核心教程 Welcome to Core Java Tutorial. I have written a lot on Core Java and Java EE frameworks. Th ...

  2. java高级教程_高级Java教程

    java高级教程 课程大纲 学习Java基础很容易. 但是,真正钻研该语言并研究其更高级的概念和细微差别将使您成为一名出色的Java开发人员. 网络上充斥着"软","便宜 ...

  3. 实用java教程_实用Java教程 目录

    目录 第一部分 面向对象基础 第1章 对象和类 ------------1 1.1   对象和类 -------------1 1.2   创建对象 -------------1 1.3   调用方法 ...

  4. java贪吃蛇教程_用Java做的贪吃蛇,简单版......

    效果图片: : 话不多说,上代码: 一共三个类: ① public class Body { int x; int y; public Body(int x, int y) { this.x = x; ...

  5. java ee6教程_《Java EE 6 企业级应用开发教程》怎么样_目录_pdf在线阅读 - 课课家教育...

    第1章 java EE概述 1.1 Java EE的产生与发展 1.2 Java EE 6架构 1.3 Java EE 6常用技术 1.4 Java EE 6特性 1.5 Java EE 6应用服务器 ...

  6. canvas 制作简易涂鸦画板(教程)

    公司大电视机是安卓系统而且系统,但因为突然无法联网又不允许第三方应用程序,但零时需要画板功能.所以就简单做个画板工具代替一下. 1.在canvas中获取光标坐标 获取坐标的代码很简单: <!DO ...

  7. java array缓存_有java数组

    [JAVA零基础入门系列]Day10 Java中的数组 [JAVA零基础入门系列](已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 D ...

  8. java初学课程_作为java新手应该学习什么课程

    照目前IT行业发展趋势,学java的人越来越多,因为java的应用范围广,薪资待遇在IT行业里也是名列前茅,那么,作为java新手应该学习什么课程呢?动力节点java学院的小编来告诉大家新手应该学哪些 ...

  9. java queue使用_使用Java使用Amazon Simple Queue Service

    java queue使用 Amazon Simple Queue Service或SQS是Amazon Webservice堆栈提供的高度可扩展的托管消息队列. Amazon SQS可用于完全解耦系统 ...

最新文章

  1. 敏捷软件开发实践——估算与计划02
  2. Windows Azure 数据安全(清理和泄漏)
  3. python进程共享内存_Python进程间通信之共享内存
  4. [BZOJ1026] [SCOI2009] windy数 (数位dp)
  5. matlab 16位灰度值转8位,在matlab中如何将灰度值为24位的转化为8?
  6. C语言-- 大端小端详解
  7. 将win server 2003 AD域升级到win server 2012 R2
  8. c# 使用GDAL处理大图
  9. Mysql 常用show命令
  10. ezmorph-1.0.6.jar的作用
  11. JPA开发求助---JPA生成数据表的时候:log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotat
  12. 查看 chrome 浏览器中的 Headers
  13. unity 企鹅砸小猪 笔记1
  14. C++ std::enable_shared_from_this
  15. sql:除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询
  16. MATLAB切比雪夫带通滤波器
  17. [xshell] xshell 及 xftp 官网无法下载解决
  18. golang mysql批量插入实例
  19. QQ互联一直显示“未提交审核”
  20. python PyEnchant(拼写检查)

热门文章

  1. linux探测路由器重启,openwrt命令实现网络不通,自动重启路由器,重新拨号或者重启wifi...
  2. 微信公众号开发(一):注册公众号,后台与微信连接
  3. 原创分析:iOS 中使用 Mobile Installation 安装 IPA(使用iTunes/AppStore一样的安装API)
  4. JavaCV的摄像头实战之八:人脸检测
  5. 通用BaseController,适用于通用mapper,减少80%单表CURD
  6. 有哪些句子给你温暖,令你感动?
  7. c语言long int怎么定义,关于c ++:定义long long int数组
  8. java 获取mysql表的大小_oracle中查询表大小和表空间大小 JAVA
  9. 这个小姐姐说:你之前所知道的区块链可能都是错的
  10. gdt描述_GDT,LDT,GDTR,LDTR 详解,包你理解透彻 | 技术部落