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 回答