之前在学习canvas时总是感觉自己应该是会了,还能写一些小的画图程序,基本原理不就是一个repaint、update(还不是由自己来吊用)、paint,在监听器中调用repaint方法就可以画图了嘛,但是真的有很多细节要注意的,总结两点:
canvas.repaint()
而不能这么写repaint()
g.draw(startPoint.x, startPoint.y, e.getX(), e.getY());
那就错误了!为什么是canvas.repaint()
呢,其实这个问题很简单,但是也很容易出错,因为JFrame本身也是一个Component子类,所以它也有repaint方法,那么你在监听器中直接写了repaint方法,程序调的不是canvas的update方法,而是这个JFrame的!类似错误代码如下:
`
canvas.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
startPoint = new Point(e.getX(), e.getY());
endPoint = startPoint;
repaint();//这里是错误的,因为这里调的是JFrame的repaint方法
}
});
canvas.addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
g.drawLine(startPoint.x, startPoint.y, e.getX(), e.getY());
startPoint = new Point(e.getX(), e.getY());//注意这里要不断的刷新起始点位置
canvas.repaint();
}
});
`
为什么要不断刷新起始点位置呢?首先:因为我认为swing画的直线就是不断的是很接近的两个点连在一起,最后“拼“成了一条直线,如果不让起始点随鼠标拖动不断变化的话,那么最后画出来的你会发现是一系列有相同起点的射线,很恶心的那种。
然后就是canvas与BufferedImage的混合,其实不就是将canvas画出来的图形最后刷新到这个Image中嘛,所以在监听器方法中该画什么图形就画什么图形,最后无非就是在paint方法中,加上g.draw(image, xxx, xxx, xxx);
这里最后再附上一段“随鼠标移动画任意大小矩形的代码“:
public class DrawingBoardWithMatrix extends JFrame {
public static void main(String[] args) {
new DrawingBoardWithMatrix();
}
public DrawingBoardWithMatrix() {
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new PaintSurface(), BorderLayout.CENTER);
this.setVisible(true);
}
private class PaintSurface extends JComponent {
ArrayList shapes = new ArrayList();
Point startDrag, endDrag;
public PaintSurface() {
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// 鼠标按下去会产生一个点
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
//鼠标松开是可以创建一个矩形,将起始点归零
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
//鼠标移动时,我们只需要知道鼠标的重点位置就好
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
//初始化背景
private void paintBackground(Graphics2D g2) {
g2.setPaint(Color.LIGHT_GRAY);
for (int i = 0; i < getSize().width; i += 10) {
Shape line = new Line2D.Float(i, 0, i, getSize().height);
g2.draw(line);
}
for (int i = 0; i < getSize().height; i += 10) {
Shape line = new Line2D.Float(0, i, getSize().width, i);
g2.draw(line);
}
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground(g2);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
}
}
private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
}