简体   繁体   中英

What method is used for Keyboard keys to move stuff in Java instead of ActionListener

Hello I created a little application that moves a ball that I've painted in Java but uses ActionListener, now I am new to Java and I would like to use mey keyboard to do this. What method should be used for this? I have seen people saying KeyBindings and some people say KeyListener I tried to figure out something myself but it doesn't work. the code I've wroten is as followed:

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

}

Attaching your listener to the button has is probably not what you want. You probably want to add it to the JPanel that has the focus. And their is the catch ... the one that has the focus. Seems to be different on different platforms, and very unreliable to get your listener triggered.

Better is to opt for key bindings. The Swing keybindings tutorial contains enough sample code to illustrate how to use them.

The rest of your logic seems in order. Changing the position when the action is triggered and scheduling a repaint.

Okay, took a little longer then I'd hoped (fighting fires ;))

This basically uses a combination of Action s, key bindings and buttons...

Now I separated the ball rendering out to a separate class, this just allows me the chance to change how the ball is rendered without effecting the container...You obviously will have your own rendering process.

MAIN

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

    }

}

The Ball Pane

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

    }

}

The Ball

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

I appologise, I got a little carried away, but this basic premise works ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM