下面是我实现了按下A键图形就会像右移动的程序,这时如果用鼠标随便拖动窗口,那么窗口肯定就会被重绘,就会明显感觉到图形移动速度变快,这要怎么解决呢?
import java.awt.*;
import java.awt.event.*;public class TestRepaint {
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
new MyFrame();
}}class MyFrame extends Frame {

private int FRAME_WIDTH = 800;
private int FRAME_HEIGHT = 200;
private Image offScreenImage = null;
Oval o = new Oval();

private class RepaintThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

MyFrame() {
setTitle("Repaint");
setSize(FRAME_WIDTH,FRAME_HEIGHT);
setLocation(100, 80);
setResizable(false);
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
setVisible(false);
System.exit(0);
}
});
addKeyListener(new KeyAdapter() { @Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
o.kReleased(e);
}
});
new Thread(new RepaintThread()).start();
}

@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
o.draw(g);
} public void update(Graphics g) {
// TODO Auto-generated method stub
if(null == offScreenImage) {
offScreenImage = createImage(FRAME_WIDTH, FRAME_HEIGHT);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(getBackground());
gOffScreen.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
}
}class Oval {
private int x = 10;
private int y = 100;
private boolean b = false;

void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLUE);
g.fillOval(x, y, 50, 50);
g.setColor(c);
move();
}

public void kReleased(KeyEvent e) {
if(KeyEvent.VK_A == e.getKeyCode()) {
b = true;
}
}

void move() {
if(b) {
x += 2;
}
}
}

解决方案 »

  1.   

    如果楼主不希望在拖动时重绘干脆可以这样:修改系统的显示属性
    “显示 属性”-->“外观”-->“效果”-->“拖动时显示窗口内容”的勾去掉
    这样拖的时候,窗口就不会重绘了
      

  2.   

    你的代码感觉有点乱 不应该通过刷新控制的吧感觉你应该用个timer或者再开一个线程控制移动
      

  3.   

    import java.awt.*;
    import java.awt.event.*;public class Main {    /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            new MyFrame();
        }
    }class MyFrame extends Frame {    private int FRAME_WIDTH = 800;
        private int FRAME_HEIGHT = 200;
        private Image offScreenImage = null;
        Oval o = new Oval();    private class RepaintThread implements Runnable {        @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {
                    repaint();
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }    private class MoveThread implements Runnable {        Oval o;        MoveThread(Oval o) {
                this.o = o;
            }        @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {
                    o.move();
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }    MyFrame() {
            setTitle("Repaint");
            setSize(FRAME_WIDTH, FRAME_HEIGHT);
            setLocation(100, 80);
            setResizable(false);
            setVisible(true);
            addWindowListener(new WindowAdapter() {            @Override
                public void windowClosing(WindowEvent e) {
                    // TODO Auto-generated method stub
                    setVisible(false);
                    System.exit(0);
                }
            });
            addKeyListener(new KeyAdapter() {            @Override
                public void keyReleased(KeyEvent e) {
                    // TODO Auto-generated method stub
                    o.kReleased(e);
                }
            });
            new Thread(new RepaintThread()).start();
            new Thread(new MoveThread(o)).start();
        }    @Override
        public void paint(Graphics g) {
            // TODO Auto-generated method stub
            o.draw(g);
        }    public void update(Graphics g) {
            // TODO Auto-generated method stub
            if (null == offScreenImage) {
                offScreenImage = createImage(FRAME_WIDTH, FRAME_HEIGHT);
            }
            Graphics gOffScreen = offScreenImage.getGraphics();
            Color c = gOffScreen.getColor();
            gOffScreen.setColor(getBackground());
            gOffScreen.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
            gOffScreen.setColor(c);
            paint(gOffScreen);
            g.drawImage(offScreenImage, 0, 0, null);
        }
    }class Oval {    private int x = 10;
        private int y = 100;
        private boolean b = false;    void draw(Graphics g) {
            Color c = g.getColor();
            g.setColor(Color.BLUE);
            g.fillOval(x, y, 50, 50);
            g.setColor(c);
        }    public void kReleased(KeyEvent e) {
            if (KeyEvent.VK_A == e.getKeyCode()) {
                b = true;
            }
        }    void move() {
            if (b) {
                x += 2;
            }
        }
    }
      

  4.   

    我明白楼主的问题在什么地方了
    你的移动偏移值累加在repaint的时候必然会调用
    所以,你一拖就会让x一直加速变大所以你要把x提到repaint外面来累加改了个程序你看下
    import java.awt.*;
    import java.awt.event.*;public class TestRepaint {
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            new MyFrame1();
        }}class MyFrame1 extends Frame {
        
    private static final long serialVersionUID = 1L;
    private int FRAME_WIDTH = 800;
        private int FRAME_HEIGHT = 200;
        private Image offScreenImage = null;
        private int x = 10;
        Oval o = new Oval();
        
        private class RepaintThread implements Runnable {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while(true) {
                    repaint();
                    try {
                        Thread.sleep(500);
                        if (o.isB()) {
                         x=x+2;
                        }
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }        
        }
        
        public MyFrame1() {
            setTitle("Repaint");
            setSize(FRAME_WIDTH,FRAME_HEIGHT);
            setLocation(100, 80);
            setResizable(false);
            setVisible(true);
            addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    // TODO Auto-generated method stub
                    setVisible(false);
                    System.exit(0);
                }
            });
            addKeyListener(new KeyAdapter() {            @Override
                public void keyReleased(KeyEvent e) {
                    // TODO Auto-generated method stub
                    o.kReleased(e);
                }
            });
            new Thread(new RepaintThread()).start();
        }
        
        @Override
        public void paint(Graphics g) {
            // TODO Auto-generated method stub
            o.draw(g, x);
        }    public void update(Graphics g) {
            // TODO Auto-generated method stub
            if(null == offScreenImage) {
                offScreenImage = createImage(FRAME_WIDTH, FRAME_HEIGHT);
            }
            Graphics gOffScreen = offScreenImage.getGraphics();
            Color c = gOffScreen.getColor();
            gOffScreen.setColor(getBackground());
            gOffScreen.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
            gOffScreen.setColor(c);
            paint(gOffScreen);
            g.drawImage(offScreenImage, 0, 0, null);    
        }    
    }class Oval {
        
        private int y = 100;
        private boolean b = false;
        
        void draw(Graphics g, int x) {
            Color c = g.getColor();
            g.setColor(Color.BLUE);
            g.fillOval(x, y, 50, 50);
            g.setColor(c);
        }
        
        public void kReleased(KeyEvent e) {
            if(KeyEvent.VK_A == e.getKeyCode()) {
                setB(true);
            }
        } public void setB(boolean b) {
    this.b = b;
    } public boolean isB() {
    return b;
    }
    }
      

  5.   

    双缓冲是为了消除图片移动的闪烁,已经用了,跟repaint没有关系吧。
      

  6.   

    把两位的程序做了结合,加MoveThread线程这个方法会同时有3个线程运行,浪费系统资源,而且假如再多启动几个Repaint线程不sleep肯定一卡一卡的。 而去除move这个方法直接在主窗口里改变x也不是个事,毕竟move应该是Oval要做的事,所以就把repaint加到MoveThread里,当b为true调用move方法。