-1

Java 中的 repaint() 方法存在问题。我做了一个新线程,不断重绘屏幕。当我释放空格键时,我希望我的播放器通过设置它的位置来平稳下降,然后等待 50 毫秒并循环 20 次。相反,它会在循环中等待全部时间,然后重新绘制。我想知道为什么它不会不断地重新绘制玩家坐标的变化。谢谢你。

(编辑)感谢大家的帮助。这是我第一次使用堆栈溢出,我只有 13 岁,还在学习 java,所以我可能会再次回到教程。

我的“a”类(主要):

public class a {
    public static void main(String[] args) {
        JFrame frame = new JFrame("StickFigure Game");
        frame.setSize(740, 580);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        b board = new b();
        frame.add(board);
        frame.addKeyListener(board);
    }
}

我的“b”类(JPanel/绘图):

public class b extends JPanel implements KeyListener {
    c player = new c();

    public class MyRunnable implements Runnable {

        public void run() {
            while (true)
                repaint();
        }
    }

    MyRunnable run = new MyRunnable();

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(player.getImage(), player.getX(), player.getY(), 80, 140,
                null);
    }

    public b() {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }

    public static void slow(int n) {
        long t0, t1;
        t0 = System.currentTimeMillis();
        do {
            t1 = System.currentTimeMillis();
        } while (t1 - t0 < n);
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_D) {
            player.setPos(player.getX() + 6, player.getY());
        }
        if (e.getKeyCode() == KeyEvent.VK_A) {
            player.setPos(player.getX() - 6, player.getY());
        }
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            player.setPos(player.getX(), player.getY() - 60);
        }
    }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {

            for (int i = 0; i < 20; i++) {
                slow(50);
                player.setPos(player.getX(), player.getY() + 2);
            }
        }
    }

    public void keyTyped(KeyEvent e) {
    }
}

我的“c”类(玩家):

public class c {
    private ImageIcon i = new ImageIcon("guy.png");
    private Image img = i.getImage();
    private int x = 0;
    private int y = 100;

    public void wait(int what) {
        try {
            Thread.sleep(what);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public c() {
    }

    public Image getImage() {
        return img;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void setPos(int mx, int my) {
        x = mx;
        y = my;
    }
}
4

3 回答 3

5

我还没有完成这里的所有代码,但这里有一些提示:

  • Swing 有自己的并发机制,允许您处理 UI 更新。您可以使用Swing Timer而不是 raw Thread。相关的是使用Thread.sleep- 不要这样做,它只会阻止EDT并阻止 UI 更新。
  • Swing 油漆链机制要求您覆盖paintComponent而不是paint.
  • 始终使用键绑定而不是KeyListeners在 Swing 中。KeyListeners需要组件焦点才能与KeyEvents. Key Bindings没有这个限制。
于 2013-02-25T16:24:06.637 回答
3

“java中的repaint()方法有问题。” 您是否认为问题可能出在您的代码上?您正在阻塞事件线程并且让系统没有时间进行中间重绘。特别是,这种方法:

public static void slow (int n){
    long t0,t1;
    t0=System.currentTimeMillis();
    do{
        t1=System.currentTimeMillis();
    }
    while (t1-t0<n);
}

这个循环:

for(int i = 0;i<20;i++){
    slow(50);
    player.setPos(player.getX(), player.getY()+2);
}

不要放弃对系统的控制,以便实际发生重新绘制。使用 Swing 计时器重写那些。查看本教程以了解如何使用它们。

此外,您的线程不断repaint()在紧密循环中调用:

public void run(){
  while(true) repaint();
}

这是一个可怕的想法。您不需要以repaint()全 CPU 速度调用。对于动画来说,每 30 毫秒左右一次就可以了。同样,考虑使用 Swing 实用程序来执行此操作,而不是编写自己的循环线程。

于 2013-02-25T16:26:06.757 回答
0

repaint只是尽快绘画的“请求”。所以当你调用它时,它会尽快调用paint方法。

这里

所以基本上你只是用paint或淹没预定的电话。updatewhile(true) repaint();

Oracle 在 AWT 和 Swing 中绘制的立场

你可以做到这一点的一种方法,或者我应该说我会怎么做,是让你的c类实现KeyListener,这样当一个键被按下时(并且只有当它被按下时)你更新它的位置。

因此,将您的KeyListener方法移至 class c,在您的 class b 构造函数中,您可以添加调用this.addKeyListener(player)或创建void addPlayer(c player)添加它的方法。

于 2013-02-25T16:20:36.483 回答