how to move an object in a JPanel using the arrow keys

前端 未结 2 1401
独厮守ぢ
独厮守ぢ 2021-01-17 03:29

I am trying to create a small program with Windowbuilder that simply paints a red rectangle (called car1) in a JPanel and move it around by pressing the arrow keys; to do th

相关标签:
2条回答
  • 2021-01-17 04:17

    This is a solution:

    addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            if (key == KeyEvent.VK_LEFT) {
                car1.move_left();
                car1.repaint();
            }
            if (key == KeyEvent.VK_RIGHT) {
                car1.move_right();
                car1.repaint();
            }
        }
    });
    

    Where are the mistakes:

    1. addKeyListener: add key listener to frame, not to panel
    2. VK_KP_: use VK_ prefix instead
    3. keyTyped: use keyPressed instead

    Next step you will have to solve is removing the previous rectangles

    0 讨论(0)
  • 2021-01-17 04:20

    There are at least 3 problems:

    1. Using KeyListener. KeyListener is well known for only responding to key events which occur on components which are focusable AND have keyboard focus. A JPanel by default is not focusable, therefore it can't recieve keyboard focus. A better solution is to use the key bindings API, which allows to define the level of focus a component must have before the bindings are triggered and allows you to re-use a Action for multiple keys, reducing code duplication
    2. Overriding paint. It's highly recommended to override paintComponent instead of paint when performing custom painting. You've also failed to maintain the paint chain, which is going to cause no end of weird and wonderful paint artifacts. Painting in AWT and Swing and Performing Custom Painting for more details
    3. Using null layouts. Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

    For example...

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import javax.swing.AbstractAction;
    import javax.swing.Action;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private int xPos;
    
            public TestPane() {
                Action leftAction = new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        xPos -= 2;
                        if (xPos < 0) {
                            xPos = 0;
                        }
                        repaint();
                    }
                };
                Action rightAction = new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        xPos += 2;
                        if (xPos + 10 > getWidth()) {
                            xPos = getWidth() - 10;
                        }
                        repaint();
                    }
                };
    
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), leftAction);
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, 0), leftAction);
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_4, 0), leftAction);
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), leftAction);
    
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), rightAction);
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, 0), rightAction);
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_6, 0), rightAction);
                bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), rightAction);
            }
    
            protected void bindKeyStroke(int condition, String name, KeyStroke keyStroke, Action action) {
                InputMap im = getInputMap(condition);
                ActionMap am = getActionMap();
    
                im.put(keyStroke, name);
                am.put(name, action);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                int yPos = (getHeight() - 10) / 2;
                g2d.drawRect(xPos, yPos, 10, 10);
                g2d.dispose();
            }
    
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题