Java repaint() 方法并不总是有效

问题描述 投票:0回答:3

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

(编辑)感谢大家的帮助。这是我第一次使用 stack overflow,我才 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;
    }
}
java swing repaint
3个回答
5
投票

我没有遍历这里的所有代码,但这里有一些提示:

  • Swing 有自己的 并发机制 允许您处理 UI 更新。您可以使用 Swing Timer 而不是原始的
    Thread
    。相关的是
    Thread.sleep
    的使用 - 不要这样做,它只会阻止
    EDT
    并阻止 UI 更新。
  • Swing 油漆链机制要求您覆盖
    paintComponent
    而不是
    paint
    .
  • 在 Swing 中始终使用 Key Bindings 而不是
    KeyListeners
    KeyListeners
    需要组件焦点才能与
    KeyEvents
    交互。
    Key Bindings
    没有这个限制

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();
}

是个糟糕的主意。您不需要以全速 CPU 调用

repaint()
。每 30 毫秒左右一次对于动画来说是可以的。同样,考虑使用 Swing 实用程序来执行此操作,而不是编写自己的循环线程。


0
投票

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

这里

所以基本上你只是用

paint
淹没
update
while(true) repaint();
的预定电话。

Oracle在AWT和Swing中的绘画立场

你可以做的一种方法,或者我应该说我会怎么做,是让你的

c
类实现
KeyListener
,这样当按下一个键时(并且只有当它被按下时)你更新它的位置.

因此,将您的

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

© www.soinside.com 2019 - 2024. All rights reserved.