-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/drawing):

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 の更新を処理できる独自の同時実行メカニズムがあります。raw ではなくSwing Timerを使用できますThread。関連するのはの使用ですThread.sleep-これを行わないでください。ブロックするだけで、EDTUI の更新が妨げられます。
  • paintComponentSwing ペイント チェーン メカニズムでは、 ではなくオーバーライドする必要がありますpaint
  • Swingではなく、常にキー バインディングを使用します。と対話するには、コンポーネントのフォーカスが必要です。この制限はありません。KeyListenersKeyListenersKeyEventsKey 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 ミリ秒ごとに 1 回程度で十分です。ここでも、独自のループ スレッドを作成するのではなく、Swing ユーティリティを使用してこれを行うことを検討してください。

于 2013-02-25T16:26:06.757 に答える
0

あくまでも「おrepaint早めに塗装してください」という「お願い」です。したがって、それを呼び出すと、できるだけ早くペイント メソッドが呼び出されます。

ここから

したがって、基本的には、paintまたはupdateのスケジュールされた呼び出しをフラッディングするだけwhile(true) repaint();です。

AWT と Swing での描画に関する Oracle のスタンス

あなたがそれを行うことができる1つの方法、または私がそれを行う方法を言う必要がありcますKeyListener.

したがって、KeyListenerメソッドを classcに移動します。クラス b コンストラクターで、呼び出しを追加するthis.addKeyListener(player)か、それを追加するメソッドvoid addPlayer(c player)を作成できます。

于 2013-02-25T16:20:36.483 に答える