1

I am trying to move a circle left with a keyEvent. So far, the circle is drawn on the window but it does not move left! I feel like the problem is where I add the Window() constructor to the container. The is no output on the console to tell me that it is working. So I dont think it even reaches the KeyEvent class. Here is my code:

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;


public class Window extends JPanel {

    private static Ellipse2D.Double circle;

    public Window() {
        super();
        int width = 400;
        int height = 400;
        circle = new Ellipse2D.Double(0.5 * width, 0.9 * height,
                0.1 * width, 0.05 * height);
        addKeyListener(new MoveCircle());
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponents(g);
        Graphics2D brush = (Graphics2D) g;
        int width = getWidth();
        int height = getHeight();
        g.clearRect(0, 0, width, height);
        brush.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        brush.draw(circle);
    }

    public class MoveCircle implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("Working on top!");
            if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                System.out.println("Working on bottom!");
                circle.x++;
                repaint();
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub
        }

        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub
        }
    }

    public static void main(String[] args) {
        Window window = new Window();
        JFrame frame = new JFrame();
        Container container = frame.getContentPane();
        container.add(new Window());
        frame.addKeyEvent(window.new MoveCircle());
        frame.setSize(800, 700);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
    }
}
user1198199
  • 75
  • 3
  • 10

3 Answers3

4

Actually what is happening is this, you are adding Window to the JFrame, but the focus lies with the JFrame, so when you type on your Keyboard that thing goes to the JFrame not the KeyListener attached to the Window class. So in order to get over it, you simply have to call requestFocusInWindow() on the Window class's Object. Try this code, I had done some modification regarding EDT and stuff.

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;


public class Window extends JPanel {

    private static Ellipse2D.Double circle;
    private JFrame frame;

    public Window() {
        super();
        int width = 400;
        int height = 400;
        circle = new Ellipse2D.Double(0.5 * width, 0.9 * height,
                0.1 * width, 0.05 * height);        
    }

    public Dimension getPreferredSize()
    {
        return (new Dimension(frame.getWidth(), frame.getHeight()));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponents(g);
        Graphics2D brush = (Graphics2D) g;
        int width = getWidth();
        int height = getHeight();
        g.clearRect(0, 0, width, height);
        brush.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        brush.draw(circle);
    }

    public class MoveCircle implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("Working on top!");
            if (e.getKeyCode() == Event.ENTER) {
                System.out.println("Working on bottom!");
                double newX = circle.x - 1;
                circle.x = newX;
                repaint();
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub
        }

        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub
        }
    }

    private void createAndDisplayGUI(Window window)
    {
        frame = new JFrame();
        Container container = frame.getContentPane();       
        container.add(window);
        window.addKeyListener(new MoveCircle());        
        frame.setSize(800, 700);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
        window.requestFocusInWindow();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                Window window = new Window();
                window.createAndDisplayGUI(window);
            }
        });
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • I modified it to work correctly now and the circle now moves left and right. However I am trying to do somthing like newX = circle.x + 5.0; This is doing nothing and the only way to get the circle to move is circle.x++; I do not like how slow it moves...? – user1198199 Mar 15 '12 at 20:50
  • Had you tried using `circle.x += 5;` instead of `newX = circle.x + 5.0;` ? – nIcE cOw Mar 15 '12 at 20:54
  • Ah yes thank you. I dont know why it wouldnt accept a new assignment. Well you have saved the day and now I will continue with my game. Thank you sir! – user1198199 Mar 15 '12 at 20:57
  • Hehe, Your Welcome and Keep Smiling :-) , the answer to this is when you writing `circle.x += 5;` you are incrementing the variable `x` of `circle` object, else you have to write `circle.x = newX;` to make that thing work :-) – nIcE cOw Mar 15 '12 at 21:02
  • 3
    Good example; see also [`LinePanel`](http://stackoverflow.com/a/5797965/230513) which uses key bindings to avoid the problem. – trashgod Mar 15 '12 at 22:12
  • agree with @trashgod, lets KeyListener for whales, use KeyBindings – mKorbel Mar 15 '12 at 22:18
  • @trashgod : That example is really handy :-) , small drops can fill the Pitcher one day, this example did worked in that way for my knowledge. Thankyou for sharing that link :-) – nIcE cOw Mar 16 '12 at 04:42
1

Only the focussed component will get key events. You need to call requestFocus() at some point.

Russ Hayward
  • 5,617
  • 2
  • 25
  • 30
1

A solution would be, to add the KeyListener to the JFrame. This way all the key strokes will throw an event, when the JFrame has the focus.

Boman
  • 11
  • 1
  • you mean frame.addKeyListeners(new MoveCircle()); in the main method? – user1198199 Mar 15 '12 at 20:25
  • Yes that's what I meant, but this may not work, because MoveCircle() can only be called from Window. so my Solution is:`Window window = new Window(); container.add(window); frame.addKeyListener(window.new MoveCircle());` – Boman Mar 15 '12 at 20:29
  • And are the System.out.prints(...); executed? Or is the console empty when pressing Enter on the JFrame? – Boman Mar 15 '12 at 20:53