programmer
programmer

Reputation: 197

KeyBindings not working properly in JApplet

The class is used to start a game that I made when you press space and then restart the space when you press space in the game over screen. It works the first time when I press space and starts the game just as intended but when I come to the game over screen and press space nothing happens. I have tried to extends JFrame instead of JApplet and then it works just fine.

This is my code:

package Game;

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

public class GameTest extends JApplet{
    private PAPITest papi;
    private TestPane panel;
    private boolean inMenu = true;
    private ImageIcon ii;
    private Image image;

    public void init(){
        setFocusable(true);
        requestFocusInWindow();
        requestFocus();
        ii = new ImageIcon("Ball Jump.png");
        image = ii.getImage();
        papi = new PAPITest();
        panel = new TestPane();
        add(panel);
        setSize(600,600);
        setVisible(true);
    }

    public void paint(Graphics g){
        if(inMenu == true){
            Graphics2D g2D = (Graphics2D) g;
            g2D.drawImage(image, 0, 0, this);
            repaint();
        }
    }

    public class TestPane extends JPanel {

        public TestPane() {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "pressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), "released");

            am.put("pressed", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(inMenu == true){
                        inMenu = false;
                        remove(panel);
                        papi.setSize(600,600);
                        papi.setAlive(true);
                        add(papi);            
                        setVisible(true); 
                    }

                    if (papi.isAlive() != true){ 
                        remove(papi);
                        papi = new PAPITest();
                        papi.setSize(600,600);
                        add(papi);
                        setVisible(true);
                        repaint();    
                    } 
                }
            });

            am.put("released", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(inMenu == true){
                        inMenu = false;
                        remove(panel);
                        papi.setSize(600,600);
                        papi.setAlive(true);
                        add(papi);            
                        setVisible(true); 
                    }

                    if (papi.isAlive() != true){ 
                        remove(papi);
                        papi = new PAPITest();
                        papi.setSize(600,600);
                        add(papi);
                        setVisible(true);
                        repaint();    
                    }
                }
            });

            setFocusable(true);
            requestFocusInWindow();        
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2D = (Graphics2D) g;
            g2D.drawImage(image, 0, 0, this);
            repaint();
        }
    }
}

Upvotes: 1

Views: 357

Answers (2)

camickr
camickr

Reputation: 324197

Don't override the paint() method of the JApplet.

public void paint(Graphics g){
    if(inMenu == true){
        Graphics2D g2D = (Graphics2D) g;
        g2D.drawImage(image, 0, 0, this);
        repaint();
    }
}

Custom painting is done in the paintComponent() method of your JPanel.

Upvotes: 1

MadProgrammer
MadProgrammer

Reputation: 347334

Your JPanel is block the KeyListener

KeyListener will only respond to events when the component they are registered to is focusable and has focus.

You should use Key Bindings instead. They allow you to register interest in keys even when the component they are registered against doesn't have direct focus.

Also, you should be calling super.paint, in fact, you shouldn't be overriding the paint method of a top level container at all.

Create a custom JPanel and override it's paintComponent method (making sure you call super.paintComponent) and replace for the panel you're adding to the applet

Working example

This is a working example based on the code you provided, now there was coding missing so I had to comment it out, but there is also a whole bunch of stuff that is just...weird...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class GameTest extends JApplet {

//    private PAPITest papi;
    private TestPane panel;
    private boolean inMenu = true;
    private ImageIcon ii;
    private Image image;

    public void init() {
// Don't need any of this, this will still focus from our control pane
//        setFocusable(true);
//        requestFocusInWindow();
//        requestFocus();
        setLayout(new BorderLayout());
        ii = new ImageIcon("Ball Jump.png");
        image = ii.getImage();
//        papi = new PAPITest();
        panel = new TestPane();
        add(panel);
        // Useless, the size of applet is actually normally defined by the html tags
//        setSize(600, 600);
//        setVisible(true);
    }

//    This is a very bad idea
//    This is not double buffered and you are over painting the applets
//    content.  Use a CardLayout and a series of JPanels to provide this
//    functionality or the Glass Pane...
//    You MUST call super.paint!!
//    public void paint(Graphics g) {
//        if (inMenu == true) {
//            Graphics2D g2D = (Graphics2D) g;
//            g2D.drawImage(image, 0, 0, this);
//            repaint();
//        }
//    }

    public class TestPane extends JPanel {

        public TestPane() {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "pressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), "released");

            am.put("pressed", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Space Pressed");
                    if (inMenu == true) {
                        inMenu = false;
//                        Removing the panel will remove the key binings...
//                        remove(panel);

//                        Don't have this code...
//                        Set size will have no effect as the layout manager
//                        apply it's own sizing based on the components
//                        preferred size...
//                        papi.setSize(600, 600);
//                        papi.setAlive(true);
//                        This seems a bit pointless, cause you just removed the "panel"
//                        which this now been added to...
//                        add(papi);

//                        Why call this when you've just removed it??
//                        setVisible(true);
                    }

//                    if (papi.isAlive() != true) {
//                        remove(papi);
//                        papi = new PAPITest();
//                        papi.setSize(600, 600);
//                        add(papi);
//                        setVisible(true);
//                        repaint();
//                    }
                }
            });

            am.put("released", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Space Released");
                    if (inMenu == true) {
                        inMenu = false;
//                        remove(panel);
//                        papi.setSize(600, 600);
//                        papi.setAlive(true);
//                        add(papi);
//                        setVisible(true);
                    }

//                    if (papi.isAlive() != true) {
//                        remove(papi);
//                        papi = new PAPITest();
//                        papi.setSize(600, 600);
//                        add(papi);
//                        setVisible(true);
//                        repaint();
//                    }
                }
            });

            setFocusable(true);
            requestFocusInWindow();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2D = (Graphics2D) g;
//            Don't have the image...
//            g2D.drawImage(image, 0, 0, this);
            repaint();
        }
    }
}

Upvotes: 1

Related Questions