Move circle around jpanel using keylistener

2019-09-06 02:49发布

Ok so i'm attempting to create a Jpanel that creates a circle which can then be moved around the screen. I've been going back and forth for awhile and can't seem to figure out how to get the actual thing to move for me.

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

  }
}

Here's the frame class. ^^

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

The above class is supposed to paint the objects and update them. It does paint the oval but it seems like i'm having trouble incorporating my next class.

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) {
    }

}

}

The class above appears to be where i'm going wrong. I'm not experienced with graphics so I have a feeling i'm just missing something simple.

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

}

And then this class keeps track of the ovals position and will update it when a key is pressed. (Or should)

Anyways any feedback would be appreciated. I'm sure I'm just doing some noob mistakes. Thanks in advance.

2条回答
放荡不羁爱自由
2楼-- · 2019-09-06 03:20
  1. The above code never makes use of the MoveShip class. Perhaps you meant to create an instance of this class in the main method rather instead of just a JFrame.
  2. If you change a coordinate of something (in this case Ship in the KeyListener method), and want to repaint so that change in coordinates takes affect, you should explicitly call repaint on the object you wish to paint (in this case PaintObjects).
  3. Both MoveShip and PaintObjects contain their own instance of Ship - if one instance moves it will not affect the other. Instead, create a single instance which you can share between the two class.
  4. For a KeyListener to fire, the component must have focus. You might consider using KeyBindings.
查看更多
放我归山
3楼-- · 2019-09-06 03:29

I used key bindings instead of a key listener. The advantage to using key bindings is that you can bind the WASD keys (for left handed players) and the arrow keys (for right handed players) to the same AbstractAction.

Here's the GUI I created.

Move The Circle GUI

I didn't put in any error checking to make sure the circle stays in the JPanel drawing area.

  1. I started the Swing GUI on the Event Dispatch thread by making a call to the SwingUtilities invokeLater method in the main method.

  2. I used a JFrame. The only time you override a Swing component (or any Java class) is when you want to override one or more of the class methods.

  3. The setKeyBindings method sets the WASD keys and the arrow keys to the AbstractAction method.

Here's the code.

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

    }

}
查看更多
登录 后发表回答