实例:桌面画板画板
在实现桌面画板有两个问题:
第一:如何实现在桌面上画图
第二:如何实现重绘
首先说明第一种,其实也很简单,在桌面上画图并不是真的就直接在桌面上画,而是先给桌面截个图,然后在上面画
给人产生一种假象,感觉好像在桌面一样,其实已经是在java的窗体中了
如何给桌面截图呢?先是用Robot类拿到一个桌面然后储存在BufferImage中:及BufferImage image = robot.robot.createScreenCapture(screenRect);(实例看代码)
然后就是重绘的问题了,在本例中,我打算实现类似铅笔的效果,就是自由划线
如果不写重绘方法,我想大家都应该知道,只要以缩小然后放大就没了。
我们知道,要想重绘就必须得储存每个圆的位置与大小(这里已连续画圆来实现划线),大家可能第一反应就是用数组,可是用数组是不对的,也不能说不对,至少效果时能出来,但是太占内存了,而且我们不知道会有多少个圆,所以在这里我使用Arraylist。
一开始我以为这个列队几个类都要用,干脆声明成静态变量来的方便,可是问题就来了,只要是声明成静态的,那么就会报错,越界。
后来熊哥告诉我不能声明成静态的,我去网上查了一下,我发现非静态的成员变量,存储在内存堆(heap)区,静态的成员变量存储在内存栈区.
那么也就是说,静态变量不能像非静态那样不断地向系统要内存,所以就会溢出了。
import java.awt.AWTException;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
* 桌面画图程序
*
* @author ChenZhaoMin
*
*/
public class DrawBoard extends JFrame {
private Robot robot = null;
private Toolkit tool = Toolkit.getDefaultToolkit();
private Rectangle screenRect = null;
private BufferedImage image = null;
private Graphics g;
private DrawListener dl;
private ArrayList<Integer> listX = new ArrayList<Integer>();
private ArrayList<Integer> listY = new ArrayList<Integer>();
/**
* @param args
* @throws AWTException
*/
public static void main(String[] args) throws AWTException {
DrawBoard db = new DrawBoard();
db.initUI();
}
public void initUI() throws AWTException {
// 新建机器人
robot = new Robot();//这里会抛异常,我偷个懒,就不处理了
// 新建截屏区域
int width = tool.getScreenSize().width;
int height = tool.getScreenSize().height;
screenRect = new Rectangle(0, 0, width, height);
// 创建截图固定区域的图像缓冲
image = robot.createScreenCapture(screenRect);
// 初始化窗体
this.setSize(tool.getScreenSize().width, tool.getScreenSize().height);
this.setUndecorated(true);
this.setLocationRelativeTo(null);
// 添加背景
ImageIcon icon = new ImageIcon(image);
JLabel jl = new JLabel(icon);
jl.setBounds(0, 0, this.getWidth(), this.getHeight());
this.getLayeredPane().add(jl, new Integer(Integer.MIN_VALUE));
JPanel jp = (JPanel) this.getContentPane();
jp.setOpaque(false);
this.setVisible(true);
g = this.getGraphics();
dl = new DrawListener(g, this, listX, listY);
this.addMouseMotionListener(dl);
this.addMouseListener(dl);
//实现按下esc退出程序
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventPostProcessor(new KeyEventPostProcessor() {
public boolean postProcessKeyEvent(KeyEvent e) {
if (KeyEvent.VK_ESCAPE == e.getKeyCode()) {
System.exit(0);
}
return true;
}
});
}
public void paint(Graphics g) {
super.paint(g);
// g.drawImage(image, 0, 0, null);注意一点的是如果是画出来的画那么在使用弹出菜单时会出问题
// 实现清除命令
// 重绘圆
for (int i = 0; i < listX.size(); i++) {
g.fillOval(listX.get(i), listY.get(i), Config.MIDDLESTROKE,
Config.MIDDLESTROKE);
}
}
}
package cn.czm0724;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
/**
* 画图监听器
*
* @author ChenZhaoMin
*
*/
public class DrawListener extends MouseAdapter {
private Graphics g;
private DrawBoard bd;
private JPopupMenu jpop = new JPopupMenu();
private ArrayList<Integer> listX;
private ArrayList<Integer> listY;
private int stroke = Config.MIDDLESTROKE;
public DrawListener(final Graphics g, final DrawBoard bd,
ArrayList<Integer> listX, ArrayList<Integer> listY) {
this.g = g;
this.bd = bd;
this.listX = listX;
this.listY = listY;
// 实现清除菜单
JMenuItem jmi1 = new JMenuItem("清除");
jmi1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clear();
bd.repaint();
}
});
jpop.insert(jmi1, 0);
// 实现改变笔触大小菜单
JMenu jmi2 = new JMenu("大小");
JMenuItem small = new JMenuItem("小");
small.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stroke = Config.SMALLSTROKE;
}
});
jmi2.add(small);
JMenuItem middle = new JMenuItem("中");
middle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stroke = Config.MIDDLESTROKE;
}
});
jmi2.add(middle);
JMenuItem large = new JMenuItem("大");
large.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
stroke = Config.LARGESTROKE;
}
});
jmi2.add(large);
jpop.insert(jmi2, 1);
// 实现退出菜单
JMenuItem jmi3 = new JMenuItem("退出");
jmi3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
jpop.insert(jmi3, 2);
}
// 实现事变拖拽画圆的方法
public void mouseDragged(MouseEvent e) {
int x = e.getX();
int y = e.getY();
g.fillOval(x, y, stroke, stroke);
listX.add(x);
listY.add(y);
}
// 监听鼠标右键
public void mouseClicked(MouseEvent e) {
// 监听鼠标右键
if (e.isMetaDown()) {
jpop.show(bd, e.getX(), e.getY());
}
}
public void clear() {
listX.removeAll(listX);
listY.removeAll(listY);
}
public int getStroke() {
return stroke;
}
}