2

I have created a KeyAdapter class within my JPanel class, and I tried debugging the click using System.out.println(String par1);

However it doesnt seem to work...

Here is the class:

package net.ryanshah;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class Menu extends JPanel
{
private GameFrame gf;

private Image bg = new ImageIcon("res/bg.png").getImage();

public Menu(final GameFrame parent) {
    this.gf = parent;
    int width = parent.getWidth();
    int height = parent.getHeight();

    setFocusable(true);

    addKeyListener(new MenuOperator());

    setBackground(Color.black);

    setLayout(null);
}

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

    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    int w = getWidth();
    int h = getHeight();
    g2d.drawImage(bg, 0, 0, null);
}

public class MenuOperator extends KeyAdapter {
    @Override
    public void keyPressed(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if(keyCode == KeyEvent.VK_SPACE) {
            System.out.println("LOL");
        }
    }
}
}

Does anyone know what the problem might be? I have set the key handler in the frame as well as setting the frame to be focusable..

Thanks in advance

~RyanS.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
rshah
  • 675
  • 2
  • 12
  • 32

2 Answers2

2

Things not considered right in the code (IMHO) :

  • The way you accessing the images in your code. Consider ImageIO, over using the constructor of ImageIcon, as the former will notify you, in case something goes wrong. For more info, please refer, Loading Image Icon Exception, for more insight.
  • KeyListeners are for AWT, Swing on the other hand uses KeyBindings.
  • Before, setting background on any JComponent prefer to first set the opaque property of the said JComponent to true. Since, opaque property is usually dependent on LookAndFeel used.
  • Avoid the use of setLayout(null), as much as possible. Please walk through the first paragraph of Absolute Positioning for more information :-)
  • THe use of ImageObserver as already mentioned in the comments.

This blog Motion Using the Keyboard by @camickr, will again add loads to your knowledge, as to why KeyListeners are not considered a better option and why KeyBindings is more suited for such needs :-)

Please have a look at this example :

import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

public class TestMenu extends JPanel {

    private Image bg;

    public TestMenu() {
        try {
            bg = ImageIO.read(
                    new URL("http://i.imgur.com/Aoluk8n.gif"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "SPACE key");
        getActionMap().put("SPACE key", keyAction);
        setOpaque(true);
        setBackground(Color.black);
    }

    private Action keyAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            System.out.println("LOL");
        }
    };

    /*
     * Make this a customary habbit to override
     * this method for the JPanel/JComponent,
     * when ever you extend any of the above classes
     */
    @Override
    public Dimension getPreferredSize() {
        return (new Dimension(200, 200));
    }

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

        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        /*
         * Here the last part of the drawImage is the 
         * ImageObserver, here it is a good practise
         * to keep the instance of the JPanel on which
         * we drawing the image to be notified, till the
         * end, till the image loading is not complete
         */
        g2d.drawImage(bg, 0, 0, this);
    }

    private void displayGUI() {
        JFrame frame = new JFrame("Painting Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        frame.setContentPane(this);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new TestMenu().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}
Community
  • 1
  • 1
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
0

Setting your panel focusable is not enough - panel cannot get focus on its own - you have to request the focus on some kind of event. For example you can add a mouse listener to your panel and call panel.requestFocusInWindow() when you click on it.

Key listener will work only if component on which you add it has focus.

Mikle Garin
  • 10,083
  • 37
  • 59
  • What exactly doesn't work? If you click on the panel with such focus-transferring mouse listener and try pressing space after - you will see that key listener works. – Mikle Garin Aug 30 '13 at 17:03
  • So i need a mouse listener too? – rshah Aug 30 '13 at 17:05
  • You need focus to be on your panel, not on some button, field or whatever else. Panel cannot just take the focus by itself, even if you set it focusable - you have to pass the focus manually using the method i mentioned. So yes, mouse listener can be an option of manual passing the focus into your panel. – Mikle Garin Aug 30 '13 at 21:02