起初的画板设计,由于系统缓存的局限,缩放画板窗体后便不能呈现画板上的对象,鉴于此,需要我们改进画板。
引进自定义队列,我们就可以“记住”画板上已画的图案,并重绘出来显示在原窗体上。
先创建一个DrawUI类,完成一般画板工作,代码如下:
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
/**
* 画图板重绘
*
* @author Administrator
*/
@SuppressWarnings("serial")
public class DrawUI extends JFrame{
public static void main(String args[]) {
new DrawUI();
}
/**
*初始化界面
*/
public DrawUI() {
this.setTitle("画图板界面");
this.setSize(600, 500);
this.setDefaultCloseOperation(3);
//设置布局
FlowLayout layout = new FlowLayout();
this.setLayout(layout);
JButton line = new JButton("直线");
//设置按钮的动作命令
line.setActionCommand("line");
JButton rect = new JButton("矩形");
rect.setActionCommand("rect");
this.add(line);
this.add(rect);
this.setVisible(true);
//创建动作监听器,加在按钮上
ButtonListener blis = new ButtonListener();
line.addActionListener(blis);
rect.addActionListener(blis);
//从窗体上获取画布对象
//获取窗体在屏幕上所占据的区域,这块区域是允许改变颜色的
java.awt.Graphics g = this.getGraphics();
DrawListener dlis = new DrawListener(g,blis,this);
//给窗体添加鼠标监听器
this.addMouseListener(dlis);
}
}
这样的画板我们是不能“记住”所绘的图案的 。需要插入自定义队列来暂时保存信息。
所以我们需要重写JFrame类中的用来绘制窗体的方法,加在DrawUI类后,代码如下:
/**
* 重写JFrame类中用来绘制窗体的方法
*/
public void paint(Graphics g){
//调用父类的方法来正确的绘制窗体
super.paint(g);
//如果数组存在,就重绘数据
if(null!= DrawListener.image){
//重绘数组
for(int i=0;i<DrawListener.image.length;i++){
for(int j=0;j<DrawListener.image[i].length;j++){
//获取颜色
int c =DrawListener.image[i][j];
//创建颜色对象
Color color = new Color(c);
g.setColor(color);
g.drawLine(j, i, j, i);
}
}
}
}
但是,这样的代码还是有错的,DrawListener和ButtonListener监听器所在的类需要我们补充完整,代码如下:
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
/**
* 画板的监听器类,实现鼠标监听器接口
*
* @author Administrator
*
*/
public class DrawListener implements java.awt.event.MouseListener {
private int x1,y1,x2,y2;
private Graphics gr;
private ButtonListener blis;
private String type = "rect";// 要绘制的形状 rect 矩形 oval 椭圆
private DrawUI du;
java.awt.Robot robot;
public static int image[][];
//创建监听器对象的时候要求传入一个画布对象
public DrawListener(Graphics gr,ButtonListener blis,DrawUI dlis){
this.gr = gr;
this.blis = blis;
this.du = dlis;
try{
robot = new java.awt.Robot();
}catch(AWTException e){
e.printStackTrace();
}
}
public DrawListener(Graphics g, ButtonListener blis2, DrawListener dlis) {
}
public void mousePressed(MouseEvent e){
// 鼠标按下时候光标的位置
x1 = e.getX();
y1 = e.getY();
}
public void mouseReleased(MouseEvent e) {
// 绘制之前先确定要绘制的形状类型
type = blis.command;
gr.setColor(new Color(0, 0, 0));
// 鼠标释放时候光标的位置
x2 = e.getX();
y2 = e.getY();
if (type.equals("line")) {
// 画直线
gr.drawLine(x1, y1, x2, y2);
} else if (type.equals("rect")) {
for (int i = 0; i < 200; i++) {
gr.setColor(new Color(i, i, i));
gr.drawRect(Math.min(x1, x2) + i, Math.min(y1, y2) - i, Math
.abs(x2 - x1), Math.abs(y2 - y1));
}
}else if (type.equals("oval")){
gr.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1),
Math.abs(y2 - y1));
}
// 获取窗体左上角的位置和窗体大小
Point p = du.getLocationOnScreen();
Dimension dim = du.getSize();
// 创建矩形对象
java.awt.Rectangle rect = new java.awt.Rectangle(p, dim);
// 截取屏幕
BufferedImage img = robot.createScreenCapture(rect);
image = new int[img.getHeight()][img.getWidth()];
//将图像按照像素分割成一个一个的点,将点的颜色存入数组
for(int i=0;i<image.length;i++){
for(int j=0;j<image[i].length;j++){
//将颜色存入数组
image[i][j] = img.getRGB(j, i);
}
}
}
public void mouseEntered(MouseEvent e) {
// System.out.println("mouseEntered");
}
public void mouseExited(MouseEvent e) {
// System.out.println("mouseExited");
}
public void mouseClicked(MouseEvent e) {
// System.out.println("mouseClicked");
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* 按钮的监听器
*
* @author Administrator
*
*/
public class ButtonListener implements ActionListener {
public String command;
public void actionPerformed(ActionEvent e) {
// 获取被点击的组件上的动作命令
command = e.getActionCommand();
System.out.println(command);
}
}
可以看到,在DrawListener类中完成了画板重绘。
代码运行后,显然还是不能满足我们的需求,因为缩放后队列是按一定顺序依次展开呈现的,而不是一次全部展现,这需要我们更向前一步,在创建队列“记住图案”后能快速重绘。
我的想法是不从自定义队列方面下手,因为队列鉴于其本质是一定先后顺序的先进先出的线性表,而这不可避免的会产生延迟,达不到我们的要求,而引进某种其他工具,能多维的,没有先后之分的拷贝窗体上的信息,这样既满足我们的要求,效率又得到了大大提高。