0

こんにちは、Java でペイントしたボールを動かす小さなアプリケーションを作成しましたが、ActionListener を使用しています。Java を初めて使用するので、キーボードを使用してこれを行いたいと思います。これにはどのような方法を使用する必要がありますか? KeyBindings と言っている人を見てきましたし、KeyListener と言う人もいます。自分で何かを理解しようとしましたが、うまくいきません。私が書いたコードは次のとおりです。

@Override
public void keyPressed(KeyEvent e) {
    System.out.println("keyPressed");

    char c = e.getKeyChar();

    if( c == KeyEvent.VK_LEFT  ) {

        pos -= 10;

    }

    repaint();
}

@Override
public void keyReleased(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent arg0) {
    System.out.println("keyTyped");
    char v = arg0.getKeyChar();
    if( v == KeyEvent.KEY_LOCATION_RIGHT ) {

        pos -= 10;

    }
    repaint();

}
4

2 に答える 2

3

ボタンにリスナーをアタッチすることは、おそらくあなたが望むものではありません。おそらくJPanel、フォーカスのある に追加する必要があります。そして、彼らはキャッチです...焦点を合わせているものです。プラットフォームごとに異なるようで、リスナーをトリガーするのは非常に信頼できません。

キーバインディングを選択することをお勧めします。Swing キーバインドのチュートリアルには、それらの使用方法を説明するのに十分なサンプル コードが含まれています。

あなたのロジックの残りの部分は順調に見えます。アクションがトリガーされたときに位置を変更し、再描画をスケジュールします。

于 2012-10-01T21:04:11.043 に答える
3

わかりました、私が望んでいたよりも少し時間がかかりました (消火活動 ;))

これは基本的に、Actions、キーバインディング、ボタンの組み合わせを使用します...

ここで、ボールのレンダリングを別のクラスに分離しました。これにより、コンテナに影響を与えずにボールのレンダリング方法を変更する機会が得られます...明らかに独自のレンダリング プロセスが必要になります。

主要

public class BallsUp {

    public static void main(String[] args) {
        new BallsUp();
    }

    public BallsUp() {
        JFrame frame = new JFrame();
        frame.setTitle("Balls up");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);

        BallPane ballPane = new BallPane();
        JPanel mainPane = new JPanel(new BorderLayout());
        mainPane.add(ballPane);

        JPanel north = new JPanel(new GridBagLayout());
        north.add(new JButton(new BallPane.UpAction(ballPane)));
        mainPane.add(north, BorderLayout.NORTH);

        JPanel south = new JPanel(new GridBagLayout());
        south.add(new JButton(new BallPane.DownAction(ballPane)));
        mainPane.add(south, BorderLayout.SOUTH);

        JPanel east = new JPanel(new GridBagLayout());
        east.add(new JButton(new BallPane.RightAction(ballPane)));
        mainPane.add(east, BorderLayout.EAST);

        JPanel west = new JPanel(new GridBagLayout());
        west.add(new JButton(new BallPane.LeftAction(ballPane)));
        mainPane.add(west, BorderLayout.WEST);

        frame.add(mainPane);
        frame.setVisible(true);

    }

}

ボールペイン

public class BallPane extends JPanel {

    protected static final int DISTANCE = 10;

    private Ball ball;

    private Timer resizeTimer;
    private ComponentListener componentListener;

    public BallPane() {

        setBall(new Ball());

        InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
        ActionMap am = getActionMap();

        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "goDown");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "goUp");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "goLeft");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "goRight");

        am.put("goDown", new DownAction(this));
        am.put("goUp", new UpAction(this));
        am.put("goLeft", new LeftAction(this));
        am.put("goRight", new RightAction(this));

        setFocusable(true);
        requestFocusInWindow();

    }

    public void setBall(Ball ball) {
        this.ball = ball;
    }

    public Ball getBall() {
        return ball;
    }

    @Override
    public void addNotify() {

        super.addNotify();

        componentListener = new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                resizeTimer.restart();
            }
        };

        resizeTimer = new Timer(250, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                removeComponentListener(componentListener);
                Point p = new Point(getWidth() / 2, getHeight() / 2);
                getBall().setLocation(p);
                resizeTimer.stop();
                resizeTimer = null;
                repaint();
            }
        });
        resizeTimer.setRepeats(false);
        resizeTimer.setCoalesce(true);

        addComponentListener(componentListener);

    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Ball ball = getBall();
        if (ball != null) {

            Graphics2D g2d = (Graphics2D) g;
            ball.paint(g2d);

        }

    }

    public static abstract class AbstractBallAction extends AbstractAction {

        private BallPane pane;

        public AbstractBallAction(BallPane pane) {
            this.pane = pane;
        }

        public BallPane getBallPane() {
            return pane;
        }

        public int getXDistance() {
            return 0;
        }

        public int getYDistance() {
            return 0;
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            BallPane pane = getBallPane();
            Ball ball = pane.getBall();

            Point location = ball.getLocation();
            location.y += getYDistance();
            location.x += getXDistance();
            if (location.y < (ball.getWidth() / 2)) {
                location.y = (ball.getWidth() / 2);
            } else if (location.y > pane.getHeight() - 1 - ball.getHeight()) {
                location.y = pane.getHeight() - ball.getHeight();
            }
            if (location.x < (ball.getHeight() / 2)) {
                location.x = (ball.getHeight() / 2);
            } else if (location.x > pane.getWidth() - 1 - ball.getWidth()) {
                location.x = pane.getWidth() - ball.getWidth();
            }
            ball.setLocation(location);
            pane.repaint();
        }

    }

    public static class UpAction extends AbstractBallAction {

        public UpAction(BallPane pane) {
            super(pane);
            putValue(NAME, "Up");
        }

        @Override
        public int getYDistance() {
            return -DISTANCE;
        }

    }

    public static class DownAction extends AbstractBallAction {

        public DownAction(BallPane pane) {
            super(pane);
            putValue(NAME, "Down");
        }

        @Override
        public int getYDistance() {
            return DISTANCE;
        }

    }

    public static class LeftAction extends AbstractBallAction {

        public LeftAction(BallPane pane) {
            super(pane);
            putValue(NAME, "Left");
        }

        @Override
        public int getXDistance() {
            return -DISTANCE;
        }

    }

    public static class RightAction extends AbstractBallAction {

        public RightAction(BallPane pane) {
            super(pane);
            putValue(NAME, "Right");
        }

        @Override
        public int getXDistance() {
            return DISTANCE;
        }

    }

}

ボール

public class Ball {

    private Shape shape;
    private Point p;

    public Ball() {
        shape = new Ellipse2D.Float(0, 0, 10, 10);
    }

    public void setLocation(Point p) {
        this.p = p;
    }

    public Point getLocation() {
        return p;
    }

    public Shape getShape() {
        return shape;
    }

    public void paint(Graphics2D g2d) {
        Point p = getLocation();
        if (p != null) {
            g2d = (Graphics2D) g2d.create();
            g2d.setColor(Color.BLUE);
            Shape shape = getShape();
            int x = (int) p.x - (shape.getBounds().width / 2);
            int y = (int) p.y - (shape.getBounds().height / 2);
            g2d.translate(x, y);
            g2d.fill(shape);
            g2d.dispose();
        }
    }

    public int getWidth() {
        return getShape().getBounds().width;
    }

    public int getHeight() {
        return getShape().getBounds().width;
    }
}

申し訳ありませんが、少し夢中になりましたが、この基本的な前提は機能します;)

于 2012-10-02T00:23:37.947 に答える