java swing canvas小结

之前在学习canvas时总是感觉自己应该是会了,还能写一些小的画图程序,基本原理不就是一个repaint、update(还不是由自己来吊用)、paint,在监听器中调用repaint方法就可以画图了嘛,但是真的有很多细节要注意的,总结两点:

  1. Canvas是一个component组件,那么在它的方法监听中要canvas.repaint() 而不能这么写repaint()
  2. 在画直线的时候一定要记得时刻更新你的起始点位置,如果认为起始点位置不变,这么写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));
        }
    }
}

你可能感兴趣的:(Java)