Hello,how are you~( ̄▽ ̄~)~
之前实现了一个完整的画图程序,并用了数组来实现重绘,数组是所有数据结构中存储和获取速度最快的一种。但是呢,数组用起来还是不太方便。
因为如果你要存储的数据不确定时,数组在创建时需要给予的长度就是缺点:若创建数组小了,存储不下数据;若创建数组大了,浪费内存空间。
还有就是,因为数组在创建时需要指定固定的一种数据类型,如果在项目的两一个位置需要存储N种数据类型,那数组就做不到了;这样数组在创建时需要指定固定的类型就会是缺点。
So,我们就要用到数组列表了哦。
1. 数组列表的实现原理:借助于数组名中存储的是数组对象在内存中的首地址。
长度固定
Object[] array = new Object[10];
Object[] array1 = new Object[11];
数组名中存储的是数组在内存中的首地址。
数据类型
在定义数组的时候,不指定数组的数据类型,而是使用泛型。
泛型在Java中不是数据类型,只是一个用来表示数据类型的符号。
泛型的表示符号:E、K、V、...
基本数据类型不可以是泛型,像 int,char 等这些不可以
2.数组列表的实现
添加数据
删除数据
插入数据
获取数据
更新数据
获取数组列表中存储的元素个数
数组列表就是使用一个类来封装对数组的操作。
MyArrayList.java
3.现在用数组列表来实现画图程序的重绘
package SummerCamp7;
/**
* 自定义数组队列 封装对数组的操作
* 表示改变支持泛型。
*/
public class MyArrayList {
// 声明一个数组名
private Object[] array;
// 声明一个记录存储元素总数的属性名
private int size;
/**
* 构造方法
*/
public MyArrayList() {
array = new Object[1];
}
/**
* 添加元素额到数组队列中的方法
*/
public void add(E e) {
if (size == 0)
array[0] = e;
else {
// 根据所添加元素的的个数来创建新的数组,新数组的长度是size+1
Object[] newArray = new Object[size + 1];
// 将新元素e添加到newArray数组的末尾
newArray[size] = e;
// 将原始数组中的数据存入到新数组中
for (int i = 0; i < size; i++) {
newArray[i] = array[i];
}
// 新数组的地址赋给原始数组
array = newArray;
}
// 记录元素总数增加1.
size++;
}
/**
* 向数组队列中指定的位置插入一个新的元素
*
*i要插入元素的所在的索引位置, e要插入的新元素
* @return 返回true表示插入成功,返回false表示插入失败
*/
public boolean add(int i, E e) {
return false;
}
/**
* 根据指定的索引位置,从数组队列中移除一个元素
*
* i要移除元素所在的索引位置
* 返回null表示移除失败,否则会返回移除的元素
*/
public E remove(int i) {
return null;
}
/**
* 移除指定的元素
*
* e要移除的元素
* 返回值true表示执行成功,返回false表示执行失败
*/
public boolean remove(E e) {
return false;
}
public boolean removeAll(E e) {
return false;
}
/**
* 修改指定索引位置的元素
*
* i要更新元素的位置
* e新的元素
* 返回值true表示执行成功,返回false表示执行失败
*/
public boolean update(int index, E e) {
return false;
}
/**
* 修改指定元素的内容
*
* je要修改的元素
* e新的元素
* 返回值true表示执行成功,返回false表示执行失败
*/
public boolean update(E je, E e) {
return false;
}
/**
* 获取数组队列中存储的元素总数
*
* 返回数组队列中存储的元素总数属性
*/
public int size() {
return size;
}
/**
* 获取指定索引位置的元素
*
* index要获取元素的索引位置
* 返回null表示获取失败,否则会返回获取到的元素
*/
@SuppressWarnings("unchecked")
public E get(int index) {
if (index < 0 || index >= size)
return null;
return (E)array[index];
}
}
package SummerCamp71;
import java.awt.AWTException;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
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.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JButton;
import SummerCamp6.Shape;
import SummerCamp6.Shape3DRect;
import SummerCamp6.ShapeCircle;
import SummerCamp6.ShapeEraser;
import SummerCamp6.ShapeFillRect;
import SummerCamp6.ShapeGum;
import SummerCamp6.ShapeImage;
import SummerCamp6.ShapeLine;
import SummerCamp6.ShapeRoundRect;
import SummerCamp6.ShapeStar;
import SummerCamp6.ShapeString;
import SummerCamp7.MyArrayList;
/**
* 1.定义DrawListenerWithArrayList事件处理类,该类要实现ActionLIstener动作事件接口、
* MouseListener鼠标事件接口和MouseMotionListener鼠标移动事件接口,
*/
public class DrawListenerWithArrayList implements ActionListener, MouseListener,
MouseMotionListener {
private String type = "铅笔";// 声明图形属性,用来存储用户选择的图形
private Color color = Color.black;// 声明颜色属性,用来存储用户选择的颜色
private Graphics g;// 声明Graphics画笔类的对象名属性
private int t1, t2, t3, t4, count = 0;
private int x1, y1, x2, y2;// 坐标
private Shape shape;// 声明图形对象名
Random r = new Random();
public BasicStroke s1;// 画笔大小
BasicStroke s = new BasicStroke();
private MyArrayList mal;// 声明一个存储图形的数组队列对象名
/**
* 构造方法
*
* @param mal对象是从DrawMain类中传递过来存储图形的数组队列对象
* 。
*/
public DrawListenerWithArrayList(MyArrayList mal) {
this.mal = mal;
}
public void setG(Graphics g) {
this.g = g;
}
/**
* 重写ActionListener接口中的actionPerformed抽象方法。
*/
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();// 获取事件源对象
String text = button.getText();// 获取按钮上的文字信息
if (text == null || text.equals("")) {// 判断是否点击的是颜色按钮
color = button.getBackground();// 获取按钮的背景颜色
System.out.println("color = " + color);
} else {
type = button.getText();// 获取按钮上的文字信息
System.out.println("text = " + text);
}
}
/**
* 当你在事件源对象上发生鼠标按键按下动作时执行此方法
*/
public void mousePressed(MouseEvent e) {
// 2.在重写的按下动作和释放动作的事件处理方法中,在按下方法中获取按下坐标值
x1 = e.getX();
y1 = e.getY();
// //设置画笔的颜色
// g.setColor(color);
if (type.equals("吸管")) {
try {
x1 = e.getXOnScreen();
y1 = e.getYOnScreen();
// 创建一个机器人对象
Robot jiqiren = new Robot();
// 2.构造一个矩形区域,这个区域就是你要获取颜色的区域
Rectangle rec = new Rectangle(x1, y1, 1, 1);
BufferedImage ima = jiqiren.createScreenCapture(rec);
// 3.获取图片的背景像素点颜色:三原色red blue green,获取图片指定像素点颜色
int a = ima.getRGB(0, 0);
color = new Color(a);
// 4.把颜色设置到画笔上
} catch (AWTException e2) {
e2.printStackTrace();
}
}
}
/**
* 当你在事件源对象上发生鼠标按键释放动作时执行此方法
*/
public void mouseReleased(MouseEvent e) {
// 2.在重写的按下动作和释放动作的事件处理方法中,在释放方法中获取释放的坐标值;
x2 = e.getX();
y2 = e.getY();
// 2.之后根据按下和释放的坐标值,以及图形和颜色,使用Graphics来绘制对应的图形。
if (type.equals("直线")) {
// // System.out.println(">>>>>" + g);
// g.drawLine(x1, y1, x2, y2);// 调用绘制直线的方法
// 根据数据来实例化图形对象
shape = new ShapeLine(x1, y1, x2, y2, color, new BasicStroke(1));
// 调用图形的绘图方法
shape.draw((Graphics2D) g);
} else if (type.equals("任意多边形")) {
if (count == 0) {
shape = new ShapeLine(x1, y1, x2, y2, color, new BasicStroke(1));
// 调用图形的绘图方法
shape.draw((Graphics2D) g);
count++;
t1 = x1;
t2 = y1;
}
else if (count != 0) {
shape = new ShapeLine(t3, t4, x2, y2, color, new BasicStroke(1));// 点击鼠标该点与前一个点相连
// 调用图形的绘图方法
shape.draw((Graphics2D) g);
if (e.getClickCount() == 2) {// 双击鼠标则闭合线段,该最新的点与最早的点相连接,闭合图形
shape = new ShapeLine(t1, t2, x2, y2, color, new BasicStroke(1));
shape.draw((Graphics2D) g);
count = 0;
}
// 记录目前该点的位置
}
t3 = x2;
t4 = y2;
} else if (type.equals("圆角矩形")) {
shape = new ShapeRoundRect(Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x1 - x2), Math.abs(y1 - y2), color,
new BasicStroke(), 30, 30);
shape.draw((Graphics2D) g);
} else if (type.equals("填充圆")) {
shape = new ShapeCircle(x1, y1, x2, y2, color, s);
shape.draw((Graphics2D) g);
} else if (type.equals("五角星")) {
shape = new ShapeStar(x1, y1, x2, y2, color, s);
shape.draw((Graphics2D) g);
}
if (shape != null) {
// 调用绘制图形的方法
shape.draw((Graphics2D) g);
// 将shape对象存入到mal数组队列对象中
mal.add(shape);
}
}
/**
* 当鼠标在窗体上按下按键并且拖动时执行此方法
*/
public void mouseDragged(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
Graphics2D g2d = (Graphics2D) g;
if (type.equals("铅笔")) {
// 根据数据来实例化图形对象
shape = new ShapeLine(x1, y1, x2, y2, color, new BasicStroke(1));
// 调用图形的绘图方法
mal.add(shape);
shape.draw((Graphics2D) g);
x1 = x2;
y1 = y2;
} else if (type.equals("刷子")) {
// 根据数据来实例化图形对象
shape = new ShapeLine(x1, y1, x2, y2, color, new BasicStroke(10));
// 调用图形的绘图方法
mal.add(shape);
shape.draw((Graphics2D) g);
x1 = x2;
y1 = y2;
} else if (type.equals("喷枪")) {
g2d.setColor(color);
shape = new ShapeGum(x1, y1, x2, y2, color, s);
mal.add(shape);
shape.draw((Graphics2D) g);
x1 = x2;
y1 = y2;
} else if (type.equals("橡皮")) {
shape = new ShapeEraser(x1, y1, x2, y2, color, s);
mal.add(shape);
shape.draw((Graphics2D) g);
x1 = x2;
y1 = y2;
} else if (type.equals("图片")) {
shape = new ShapeImage(color, x1, y1, x2, y2);
shape.draw((Graphics2D) g);
} else if (type.equals("填充矩形")) {
shape = new ShapeFillRect(Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x1 - x2), Math.abs(y1 - y2), color,
new BasicStroke(1));
if (shape != null) {
// 调用绘制图形的方法
shape.draw((Graphics2D) g);
// 将shape对象存入到mal数组队列对象中
mal.add(shape);
}
shape.draw((Graphics2D) g);
} else if (type.equals("文字")) {
shape = new ShapeString(x1, y1, x2, y2, color, s);
if (shape != null) {
// 调用绘制图形的方法
shape.draw((Graphics2D) g);
// 将shape对象存入到mal数组队列对象中
mal.add(shape);
}
shape.draw((Graphics2D) g);
} else if (type.equals("3d矩形")) {// 7.3d矩形
shape = new Shape3DRect(x1, y1, x2, y2, color, s);
if (shape != null) {
// 调用绘制图形的方法
shape.draw((Graphics2D) g);
// 将shape对象存入到mal数组队列对象中
mal.add(shape);
}
shape.draw((Graphics2D) g);
}
}
/**
* 当鼠标在窗体上移动鼠标时执行此方法
*/
public void mouseMoved(MouseEvent e) {
}
/**
* 当你在事件源对象上发生鼠标点击(按下和释放的动作必须在同一个位置上)动作时执行此方法
*/
public void mouseClicked(MouseEvent e) {
}
/**
* 当你的鼠标光标进入事件源对象上时执行此方法
*/
public void mouseEntered(MouseEvent e) {
}
/**
* 当你的鼠标光标离开事件源对象上时执行此方法
*/
public void mouseExited(MouseEvent e) {
}
}
package SummerCamp71;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import SummerCamp6.Shape;
import SummerCamp7.MyArrayList;
@SuppressWarnings("serial")
public class DrawMain extends JPanel {
JFrame frame=new JFrame();
public static void main(String[] args) {
new DrawMain().initUI();
}
// 实例化数组列表对象,指定要存储的类型是Shape类型的。
private MyArrayList mal = new MyArrayList();
/**
* 初始化界面的方法
*/
public void initUI() {
frame.setTitle("依米的画图板");
frame.setDefaultCloseOperation(3);
frame.setSize(1000, 700);
frame.setLocationRelativeTo(null);
/**
* 3.在DrawMain类的initUI方法中,实例化DrawListener事件处理类的对象,对象名命名为dl。
*/
DrawListenerWithArrayList dl = new DrawListenerWithArrayList(mal);
JPanel panel1 = new JPanel(); // 北边面板(存放铅笔,喷枪等工具按钮)
panel1.setPreferredSize(new Dimension(120, 50));
panel1.setBackground(Color.gray);
frame.add(panel1, BorderLayout.NORTH);
String[] str1 = { "铅笔", "刷子", "喷枪", "吸管", "橡皮" };
for (int i = 0; i < str1.length; i++) {
JButton button_1 = new JButton(str1[i]);
panel1.add(button_1);
button_1.setPreferredSize(new Dimension(110, 30));
button_1.addActionListener(dl);
}
JPanel panel2 = new JPanel(); // 西边面板(存放图形按钮)
panel2.setPreferredSize(new Dimension(130, 800));
panel2.setBackground(Color.gray);
frame.add(panel2, BorderLayout.WEST);
String[] str2 = { "直线", "填充圆", "文字", "图片", "圆角矩形", "填充矩形", "3d矩形", "五角星",
"任意多边形" };
for (int i = 0; i < str2.length; i++) {
JButton button_2 = new JButton(str2[i]);
panel2.add(button_2);
button_2.setPreferredSize(new Dimension(120, 30));
button_2.addActionListener(dl);
}
JPanel panel3 = new JPanel(); // 东边面板(存放颜色按钮)
panel3.setPreferredSize(new Dimension(130, 800));
panel3.setBackground(Color.gray);
frame.add(panel3, BorderLayout.EAST);
// 定义Color数组,用来存储按钮上要显示的颜色信息
Color[] colorArray = { Color.BLUE, Color.GREEN, Color.RED, Color.BLACK,
Color.lightGray, Color.ORANGE, Color.PINK,
new Color(123, 100, 132) };
// 循环遍历colorArray数组,根据数组中的元素来实例化按钮对象
for (int i = 0; i < colorArray.length; i++) {
JButton button = new JButton();
button.setBackground(colorArray[i]);
button.setPreferredSize(new Dimension(50, 50));
// 4.将事件源按钮对象通过addActionListener()监听方法和事件处理类dl对象绑定。
button.addActionListener(dl);
panel3.add(button);
}
frame.add(this, BorderLayout.CENTER);
frame.setBackground(this.getBackground());
frame.setVisible(true);// 可见必须在gr之前,否则看不到画笔
Graphics gr = this.getGraphics();// 从窗体上获取画笔对象
this.addMouseListener(dl);
this.addMouseMotionListener(dl);
dl.setG(gr);
}
// 声明图形对象数组,数组的能存储的元素个数是10000个图形
/**
* 重写组件的paint方法
*/
/**
* 重写组件的绘制方法
*/
public void paint(Graphics g) {
super.paint(g);// 通过super调用父类的paint方法
System.out.println(">>>>>");//记录重绘的次数
for(int i=0;i
Shape shape = mal.get(i);//从数组队列中获取图形对象
shape.draw((Graphics2D)g);//调用绘制图形的方法
}
}
}
实现效果跟上一篇Java画图程序和重绘一样,童鞋们可以翻一下,或者自己动手写一个,很简单有没有╮( ̄▽ ̄)╭,写好就可以去撩妹了,各种技能up。
代码上都标注了注释,相信童鞋们都看得懂代码段,我就拉出来一一介绍了,另外讲一下我的五角星算法画出来的五角星的两个脚有点长,正好符合现在的时尚潮流,好吧 ,其实是我不想算下去了(→o←),有兴趣的童鞋可以通过圆心距这个方法来画,不会就自己百度吧,OK,差不多就是这些啦,以后会继续更新,么么哒。