A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 余明辉 中级黑马   /  2012-7-31 23:34  /  2983 人查看  /  8 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

效果是:鼠标按下以后,在鼠标移动过的轨迹上,画出一条线,这个线是用很多点组成的
但是我做出来运行以后发现,如果鼠标移动的慢点,画的线还挺好的,如果鼠标移动的快的话,就变成一个个点了
源码在下面,帮忙看下要怎么解决
import java.awt.*;
import java.util.*;
import java.awt.event.*;

public class GraphicsDemo {
        public static void main(String[] args) {
                new FrameFF("draw....");
        }
}

class FrameFF extends Frame {
        ArrayList<Point> points;                //声明容器,作用是存储点对象
        FrameFF(String s) {               
                super(s);
                points = new ArrayList<Point>();       
                setBounds(300,150,500,500);       
                setVisible(true);
               
                //添加鼠标监听
                addMouseMotionListener(new MouseMotionAdapter() {
                        public void mouseDragged(MouseEvent e) {
                                FrameFF f = (FrameFF)e.getSource();
                                Point p = new Point(e.getX(),e.getY());
                                f.addPoint(p);
                                f.repaint();
                        }                       
                });
               
                //窗口关闭
                addWindowListener(new WindowAdapter(){
                        public void windowClosing(WindowEvent e) {
                                System.exit(0);
                        }
                });
        }
       
        public void paint(Graphics g) {
                Color c = g.getColor();       
                for(Iterator<Point> it=points.iterator(); it.hasNext(); ) {
                        Point p1 = (Point)it.next();
                        g.setColor(new Color(123,44,82));
                        g.fillOval(p1.x, p1.y, 4, 4);               

                }
                g.setColor(c);
        }
       
        public void addPoint(Point p){
                points.add(p);
        }
}

评分

参与人数 1技术分 +1 收起 理由
田建 + 1 赞一个!

查看全部评分

8 个回复

倒序浏览
你好,这个问题我看了下。应该这么来做:
public void paint(Graphics g) {
                Color c = g.getColor();        
                for(Iterator<Point> it=points.iterator(); it.hasNext(); ) {
                        Point p1 = (Point)it.next();
                        g.setColor(new Color(123,44,82));
                        if(prePoint == null){
                                g.fillOval(p1.x, p1.y, 4, 4);
                        }
                        else{
                                g.drawLine(prePoint.x, prePoint.y, p1.x, p1.y);
                        }
                        prePoint = p1 ;

                }
                prePoint = null ;
                g.setColor(c);
        }
解释如下:鼠标拖动时,两次鼠标事件的触发需要一定的时间。而当鼠标拖动过快时,就会看到两点之间的距离--->你出现的这个问题。但是这个距离是很小的,所以通过将两点画上直线完成图形的绘制。由于距离极短,我们是无法分辨的。
关于代码改进意见:由于awt的每次都要绘制全部,所以应该说代码质量不是很高。建议使用BufferedImage类,创建一个和画图区相同大小的image,使用getGraphics得到Graphics,每次调用鼠标时绘制到此Graphics上,然后在组件的paint中一次性绘制,这样就不必使用集合了。  另外我觉得使用Swing中的JPanel还是比较省事的,因为缓冲已经做好了。而且没有闪屏现象。。。
回复 使用道具 举报
改进后的代码如下:
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;


public class GraphicsDemo {
        public static void main(String[] args) {
                new FrameFF("draw....");
        }
}

class FrameFF extends Frame {
                //frame大小
        private static final int AREA_LENGTH = 500 ;
        //记录先前位置。置为-1的原因请见MouseMotionListener
        private int preX = -1 ;
        private int preY = -1 ;
        //用做缓冲。。
        private BufferedImage image = new BufferedImage(AREA_LENGTH,AREA_LENGTH,BufferedImage.TYPE_INT_BGR);
        Graphics g = image.getGraphics();
        FrameFF(String name) {               
                super(name);      
                setBounds(300,150,AREA_LENGTH,AREA_LENGTH);        
                setVisible(true);
                //将底色置为白色,便于观看
                g.fillRect(0,0,AREA_LENGTH,AREA_LENGTH);
                //添加鼠标监听
                addMouseMotionListener(new MouseMotionAdapter() {
                        public void mouseDragged(MouseEvent e) {
                                //均大于0时肯定已经在内部了,且已经点击过一次,记录下了第一次的坐标
                                //所以这时划线已经没有问题了
                                        if(preX >0 && preY > 0 ){
                                                g.setColor(new Color(123,44,82));
                                                g.drawLine(preX, preY, e.getX(), e.getY());
                                        }
                                        preX = e.getX();
                                        preY = e.getY();
                                        //看你原先的代码还需要得到事件源,其实没有必要,因为是Frame
                                        //的内部,所以其属性是可以访问的,直接调用其方法即可
                                repaint();
                        }                        
                });
               
                //窗口关闭
                addWindowListener(new WindowAdapter(){
                        public void windowClosing(WindowEvent e) {
                                System.exit(0);
                        }
                });
        }   
        public void paint(Graphics g) {
                //整体绘制,免去每次集合遍历时间和重新绘制所有点时间。应该会剩下不少时间的,虽然感觉不到,呵呵
                g.drawImage(image,0,0,null);
        }
}
希望可以帮到你  
回复 使用道具 举报
陈潼 发表于 2012-8-1 09:17
改进后的代码如下:
import java.awt.Color;
import java.awt.Frame;

感谢你的回答,我运行了下,发现画出来的线都是连着的,这个差别有点大,我想要的效果是,就只在鼠标按下去经过的地方才画线条,今天调试了一下你的代码,暂时还没想出解决的方案
回复 使用道具 举报
余明辉 发表于 2012-8-1 21:08
感谢你的回答,我运行了下,发现画出来的线都是连着的,这个差别有点大,我想要的效果是,就只在鼠标按下 ...

不明白你想表达的是什么意思。这样不就是字鼠标按下后,经过的地方画出么?不是画图工具中的画笔么?
那是什么?
回复 使用道具 举报
陈潼 发表于 2012-8-1 22:09
不明白你想表达的是什么意思。这样不就是字鼠标按下后,经过的地方画出么?不是画图工具中的画笔么?
那 ...

鼠标抬起来的地方有个点,然后鼠标换个地方再按下又是另外一个点,这2个点之间有一条线啊,如果用画图工具来画,并不会这样啊
回复 使用道具 举报
余明辉 发表于 2012-8-1 22:15
鼠标抬起来的地方有个点,然后鼠标换个地方再按下又是另外一个点,这2个点之间有一条线啊,如果用画图工 ...

刚看到 确实是我疏忽了 可以这样改进: 加入MouseListener 监听鼠标放开
addMouseListener(new MouseAdapter(){
                    public void mouseReleased(MouseEvent e){
                                preX = -1 ;
                            preY = -1 ;
                    }
                });

评分

参与人数 1技术分 +1 收起 理由
田建 + 1 赞一个!

查看全部评分

回复 使用道具 举报
很棒,太谢谢你了!
回复 使用道具 举报
问题已经解决
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马