使用keylistener在jpanel周围移动圆圈

时间:2015-05-07 16:40:10

标签: java swing graphics actionlistener keylistener

好的,我试图创建一个创建圆圈的Jpanel,然后可以在屏幕上移动。我已经来回走了一段时间,似乎无法弄清楚如何让实际的东西为我移动。

package astroidlab;

import java.awt.BorderLayout;
import javax.swing.JFrame;

public class MainFrame {
    public static void main(String[] args) {
      //components
    JFrame jf = new JFrame();
    PaintObjects po = new PaintObjects();


    jf.setLayout(new BorderLayout());
    jf.add(po, BorderLayout.CENTER);

    jf.setVisible(true);
    jf.setSize(300, 300);
    jf.setLocationRelativeTo(null);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  }
}

这是框架类。 ^^

package astroidlab;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JPanel;
import javax.swing.Timer;

public class PaintObjects extends JPanel implements ActionListener{
//global variable
Ship s = new Ship();

//constructor
public PaintObjects() {
    super();

    Timer t = new Timer(50, this);
    t.start();
}

@Override
public void paintComponent(Graphics g) {
        super.paintComponents(g);
        g.setColor(Color.BLACK);

        g.fillOval(s.getXpos(),  s.getYpos(),  s.getHeight(),  s.getWidth());

}

@Override
public void actionPerformed(ActionEvent ae) {
    int xpos = s.getXpos();
    int ypos = s.getYpos();


    repaint();
}
}

上面的类应该绘制对象并更新它们。它确实画了椭圆形,但似乎我在下一堂课时遇到了麻烦。

package astroidlab;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class MoveShip extends JFrame{
Ship s = new Ship();

public MoveShip() {

    ballMover bm = new ballMover();
    this.addKeyListener(bm);

}

private class ballMover implements KeyListener {

    @Override
    public void keyPressed(KeyEvent ke) {
        if(ke.getKeyCode() == 37) {
            s.goLeft();
        }
        if(ke.getKeyCode() == 39) {
            s.goRight();
        }
        if(ke.getKeyCode() == 38) {
            s.goUp();
        }
        if(ke.getKeyCode() == 40) {
            s.goDown();
        }
    }

    @Override
    public void keyReleased(KeyEvent ke) {
    }

    @Override
    public void keyTyped(KeyEvent ke) {
    }

}

}

上面的课程似乎是我出错的地方。我没有图形经验,所以我有一种感觉,我只是错过了一些简单的东西。

package astroidlab;

public class Ship {
//fields
int xpos = 0;
int ypos = 0;
int height = 20;
int width = 20;

public Ship() {
    super();
}

//move methods
public  void goLeft() {
    xpos -= 2;
    System.out.println("xpos: " + xpos + " ypos: " + ypos);
}
public  void goRight() {
    xpos += 2;
    System.out.println("xpos: " + xpos + " ypos: " + ypos);
}

public  void goUp() {
    ypos -= 2;
    System.out.println("xpos: " + xpos + " ypos: " + ypos);
}
public  void goDown() {
    ypos += 2;
    System.out.println("xpos: " + xpos + " ypos: " + ypos);
}

//get methods
public int getXpos() {
    return xpos;
}
public int getYpos() {
    return ypos;
}
public int getHeight() {
    return height;
}
public int getWidth() {
    return width;
}

//set methods
public void setXpos() {
    this.xpos = xpos;
}
public void setYpos() {
    this.ypos = ypos;
}
public void setHeight() {
    this.height = height;
}
public void setWidth() {
    this.width = width;
}

}

然后这个类跟踪椭圆位置,并在按下键时更新它。 (或者应该)

无论如何,任何反馈都将不胜感激。我确定我只是做了一些noob错误。提前谢谢。

2 个答案:

答案 0 :(得分:1)

  1. 以上代码从不使用MoveShip类。也许您打算在main方法中创建此类的实例,而不仅仅是JFrame
  2. 如果您更改了某些内容的坐标(在本例中为KeyListener方法中的Ship),并希望重新绘制以使坐标更改生效,则应在对象上显式调用repaint希望画画(在这种情况下是PaintObjects)。
  3. MoveShipPaintObjects都包含自己的Ship实例 - 如果一个实例移动它不会影响另一个实例。相反,创建一个可以在两个类之间共享的实例。
  4. 要启动KeyListener,组件必须具有焦点。您可以考虑使用KeyBindings

答案 1 :(得分:0)

我使用了键绑定而不是键侦听器。使用键绑定的优点是,您可以将WASD键(对于左撇子玩家)和箭头键(对于右撇子玩家)绑定到相同的AbstractAction。

这是我创建的GUI。

Move The Circle GUI

我没有进行任何错误检查,以确保圆圈停留在JPanel绘图区域。

  1. 我通过调用main方法中的SwingUtilities invokeLater方法在Event Dispatch thread上启动了Swing GUI。

  2. 我使用了JFrame。您重写Swing组件(或任何Java类)的唯一时间是您想要覆盖一个或多个类方法。

  3. setKeyBindings方法将WASD键和箭头键设置为AbstractAction方法。

  4. 这是代码。

    package com.ggl.testing;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    
    import javax.swing.AbstractAction;
    import javax.swing.InputMap;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;
    import javax.swing.SwingUtilities;
    
    public class MoveCircle implements Runnable {
    
        private JFrame frame;
    
        @Override
        public void run() {
            frame = new JFrame("Move The Circle");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            CirclePanel linePanel = new CirclePanel();
            setKeyBindings(linePanel);
            frame.add(linePanel);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        private void setKeyBindings(CirclePanel circlePanel) {
            InputMap inputMap = circlePanel
                    .getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
            inputMap.put(KeyStroke.getKeyStroke("W"), "up arrow");
            inputMap.put(KeyStroke.getKeyStroke("S"), "down arrow");
            inputMap.put(KeyStroke.getKeyStroke("A"), "left arrow");
            inputMap.put(KeyStroke.getKeyStroke("D"), "right arrow");
    
            inputMap.put(KeyStroke.getKeyStroke("UP"), "up arrow");
            inputMap.put(KeyStroke.getKeyStroke("DOWN"), "down arrow");
            inputMap.put(KeyStroke.getKeyStroke("LEFT"), "left arrow");
            inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "right arrow");
    
            inputMap = circlePanel.getInputMap(JPanel.WHEN_FOCUSED);
            inputMap.put(KeyStroke.getKeyStroke("UP"), "up arrow");
            inputMap.put(KeyStroke.getKeyStroke("DOWN"), "down arrow");
            inputMap.put(KeyStroke.getKeyStroke("LEFT"), "left arrow");
            inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "right arrow");
    
            circlePanel.getActionMap().put("up arrow",
                    new ArrowAction(circlePanel, new Point(0, -10)));
            circlePanel.getActionMap().put("down arrow",
                    new ArrowAction(circlePanel, new Point(0, 10)));
            circlePanel.getActionMap().put("left arrow",
                    new ArrowAction(circlePanel, new Point(-10, 0)));
            circlePanel.getActionMap().put("right arrow",
                    new ArrowAction(circlePanel, new Point(10, 0)));
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new MoveCircle());
        }
    
        public class CirclePanel extends JPanel {
    
            private static final long serialVersionUID = 2504617322590404776L;
    
            private Point lastPoint;
    
            public CirclePanel() {
                int width = 400;
                this.setPreferredSize(new Dimension(width, width));
                this.lastPoint = new Point(width / 2, width / 2);
            }
    
            public void addPoint(int x, int y) {
                lastPoint = new Point(x, y);
            }
    
            public Point getPreviousPoint() {
                return lastPoint;
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.setColor(Color.RED);
                g.fillOval(lastPoint.x - 20, lastPoint.y - 20, 40, 40);
            }
        }
    
        public class ArrowAction extends AbstractAction {
    
            private static final long serialVersionUID = 8463453082541763265L;
    
            private CirclePanel circlePanel;
    
            private Point movePoint;
    
            public ArrowAction(CirclePanel circlePanel, Point movePoint) {
                this.circlePanel = circlePanel;
                this.movePoint = movePoint;
            }
    
            @Override
            public void actionPerformed(ActionEvent event) {
                Point p = circlePanel.getPreviousPoint();
                p.x += movePoint.x;
                p.y += movePoint.y;
                circlePanel.addPoint(p.x, p.y);
                circlePanel.repaint();
            }
    
        }
    
    }