0

そこで、Java を学びながら、円が動き回る小さな長方形の画面を表示する簡単なプログラムに取り組んできました。背景と円も色と速度が変わります。

現在、ユーザーが文字を入力すると円の方向が変わるように、KeyEvents を追加しようとしています。私は数時間 KeyEvent 機能を処理しようとしてきましたが、行き詰まっています。

プログラムがキーボード入力に応答するように、次のコードをどのように変更しますか。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.JFrame;

public class MovingCircle3 extends JFrame implements ActionListener {

    Ellipse2D.Double myEllipse;
    Rectangle2D.Double backgroundRectangle;
    private int paintTally = 0;     // Counts # of repaints.
    private int timerSpeed = 500;   // Holds speed of timer. Initially: 500ms.
    private Timer timerOjbect;
    private char shapeMoveInput = 'd';

    public MovingCircle3() {
        myEllipse = new Ellipse2D.Double(30, 30, 20, 20); // Ellipse starting point
        backgroundRectangle = new Rectangle2D.Double(0, 0, 400, 300); // Background.
        this.timerOjbect = new Timer(500, this);
        timerOjbect.start();                 //Creates and starts timer.
    }

    public static void main(String[] args) {
        System.out.print("Game Controls: \n  l = Move left. \n  r = Move right. \n  u = Move up. \n  d = Move down. \n    ENTER COMMAND: ");    // Game controls.

        MovingCircle3 b = new MovingCircle3();

        b.setVisible(true);
        b.setSize(400, 300);
        b.setVisible(true);
        b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void keyPressed(KeyEvent e) {
        try {
            shapeMoveInput = e.getKeyChar();
        } catch (Exception ex) {
            shapeMoveInput = 'd';
        }
    }

    public void actionPerformed(ActionEvent ae) {
        //This will be called by the Timer
        if (shapeMoveInput == 'l') {
            myEllipse.setFrame(myEllipse.getX() - 1, myEllipse.getY(), myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 x-pixel left 
        } else if (shapeMoveInput == 'r') {
            myEllipse.setFrame(myEllipse.getX() + 1, myEllipse.getY(), myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 x-pixel right
        } else if (shapeMoveInput == 'u') {
            myEllipse.setFrame(myEllipse.getX(), myEllipse.getY() - 1, myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 y-pixel up
        } else if (shapeMoveInput == 'd') {
            myEllipse.setFrame(myEllipse.getX(), myEllipse.getY() + 1, myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 y-pixel
        }
        repaint();
    }

    public void paint(Graphics g) {
        paintTally++; // Increments by one for every repaint().
        if (paintTally % 25 == 0) { // Take modulus 25 of paintTally to execute every 25 paints.
            timerSpeed = (int) (timerSpeed / 2);
            timerOjbect.setDelay(timerSpeed); // Divide speed by 2 and see to timer length.  
        }
        int isPaintTen = (int) (paintTally / 10);  // Divide current count by 10.
        Graphics2D g2 = (Graphics2D) g;
        if ((isPaintTen % 2) == 0) { // Take modulus to set if #/10 is odd or even.
            g2.setColor(Color.YELLOW);
            g2.fill(backgroundRectangle);
            g2.setColor(Color.RED);
            g2.draw(myEllipse);

        } else if ((isPaintTen % 2) == 1) {
            g2.setColor(Color.RED);
            g2.fill(backgroundRectangle);
            g2.setColor(Color.YELLOW);
            g2.draw(myEllipse);
        }
    }
}
4

3 に答える 3

2

1) JFrame のペイント メソッドをオーバーライドすることは絶対にしないでください。カスタム ペイントは、JPanel の paintComponent(...) メソッドをオーバーライドすることによって行われます。次に、カスタム パネルを JFrame に追加します。元の投稿のコメントに Swing チュートリアルへのリンクが記載されています。詳細と実際の例については、カスタム ペインティングのセクションを参照してください。

2) 次に、KeyListener をパネルに追加する必要があります。ただし、KeyEvents はフォーカスのあるコンポーネントにのみ渡されるため、パネルで setFocusable(...) メソッドを使用してパネルをフォーカス可能にする必要があります。

ただし、KeyListener はこの問題を解決する適切な方法ではありません。KeyListeners を使用するよりもはるかに柔軟な Key Bindings を使用する必要があります。ここでも、Swing チュートリアルに「キーバインディングの使用方法」に関するセクションがあります。

于 2010-09-15T03:01:12.213 に答える
1

KeyListener が必要なようですが、ActionListener は JFrame で動作します。キーリスナーのスーパークラスである ActionListener を実装しているようです。正しく実装していますが、その後、新しいリスナーを登録する必要があります。これにより、Swing のイベント スレッドがこのリスナーにイベントを送信します。イベント スレッドは、システム管理のスレッドです。このイベント スレッドは、oracles/Suns の Web サイトで読むことができます。また、興味がある場合は、Observer パターンを使用することに注意してください。

あなたがする必要があるのは、初期化のMovingCircle3()で次のことを行うことだけです

this.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
                movingcircle3_Function(e);
            }
        });  

または、次のことを試すこともできますが、正しく機能するかどうかはわかりません

this.addActionListener(this);

于 2010-09-15T02:33:14.960 に答える
1

とを読んでInputMapくださいActionMap。(チュートリアルはこちら) これは、キーボード ストロークを ID にマッピングし、次に ID をメソッド呼び出しにマッピングする 2 段階のプロセスです。

于 2010-09-15T02:56:43.403 に答える