ethan_collins
ethan_collins

Reputation: 113

Java: Adding a Key Listener to a JFrame

I am trying to get into graphics programming in Java and am trying a little exercise where I want to make a car go back and forth in a frame. Then I want to make it go faster or slower if I press the up or down arrow keys. However, I am not seeming to be able to add the key listener correctly. To test my code, I am only trying to print a message to the command prompt. Any help will be greatly appreciated!

The code compiles and runs as is. I get a car going back and forth in the frame. The only thing not working is the key listener.

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

public class Racing extends JFrame
{
    public static class Car extends JComponent implements ActionListener
    {
        int x=0;
        int y=0;
        int delta = 10;
        Timer timer;
        int z = 300;

        public Car()
        {
            timer = new Timer(20,this);
            timer.start();

            addKeyListener(new KeyAdapter()
            {
                @Override
                public void keyPressed(KeyEvent e)
                {           
                    if(e.getKeyCode() == KeyEvent.VK_UP)
                        System.out.println("The up key was pressed!");
                }
            });
        }

        public void paint(Graphics g)
        {
            super.paintComponent(g);

            y = getHeight();
            z = getWidth();

            g.setColor(Color.BLUE);
            g.fillRect(0, 0, z, y);

            Polygon polygon = new Polygon();
            polygon.addPoint(x + 10, y - 20);
            polygon.addPoint(x + 20, y - 30);
            polygon.addPoint(x + 30, y - 30);
            polygon.addPoint(x + 40, y - 20);

            g.setColor(Color.BLACK);
            g.fillOval(x + 10, y - 11, 10, 10);
            g.fillOval(x + 30, y - 11, 10, 10);
            g.setColor(Color.GREEN);
            g.fillRect(x, y - 21, 50, 10);
            g.setColor(Color.RED);
            g.fillPolygon(polygon);
            g.setColor(Color.BLUE);
        }

    public void actionPerformed(ActionEvent e) {
        x += delta;
        if (x > z-40) {
            delta *= -1;
            x = (z-40);
        } else if (x < 0) {
            delta *= -1;
            x = 0;
        }

        repaint();
    }

    }

    public static void main(String[] args)
    {
       JFrame frame = new JFrame("Racing");
       frame.setPreferredSize(new Dimension(600,300));
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.pack();
       frame.add(new Car());
       frame.setVisible(true);
       frame.setFocusable(true);
    }
}

Upvotes: 0

Views: 389

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347332

The short answer is don't, there are too many issues involved.

Instead, use the key bindings API. See How to Use Key Bindings for more details

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Racing extends JFrame {

    public static class Car extends JComponent implements ActionListener {

        int x = 0;
        int y = 0;
        int delta = 10;
        Timer timer;
        int z = 300;

        public Car() {
            timer = new Timer(20, this);
            timer.start();

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "goingUp");

            ActionMap am = getActionMap();
            am.put("goingUp", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("The up key was pressed!");
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            y = getHeight();
            z = getWidth();

            g.setColor(Color.BLUE);
            g.fillRect(0, 0, z, y);

            Polygon polygon = new Polygon();
            polygon.addPoint(x + 10, y - 20);
            polygon.addPoint(x + 20, y - 30);
            polygon.addPoint(x + 30, y - 30);
            polygon.addPoint(x + 40, y - 20);

            g.setColor(Color.BLACK);
            g.fillOval(x + 10, y - 11, 10, 10);
            g.fillOval(x + 30, y - 11, 10, 10);
            g.setColor(Color.GREEN);
            g.fillRect(x, y - 21, 50, 10);
            g.setColor(Color.RED);
            g.fillPolygon(polygon);
            g.setColor(Color.BLUE);
        }

        public void actionPerformed(ActionEvent e) {
            x += delta;
            if (x > z - 40) {
                delta *= -1;
                x = (z - 40);
            } else if (x < 0) {
                delta *= -1;
                x = 0;
            }

            repaint();
        }

    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Racing");
                frame.setPreferredSize(new Dimension(600, 300));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.add(new Car());
                frame.setVisible(true);
                frame.setFocusable(true);
            }
        });
    }
}

Also, don't call super.paintComponent from paint, you've basically broken the entire paint chain. Instead, override the paintComponent method itself...

Upvotes: 3

Related Questions