KeyBindings在JApplet中无法正常工作

时间:2013-04-12 08:16:49

标签: java swing applet key-bindings japplet

该类用于启动我按下空格时制作的游戏,然后在屏幕上按下游戏中的空格时重新启动空间。当我按空间并按照预期开始游戏时,它第一次工作,但是当我通过屏幕来到游戏并按空间时没有任何反应。我试图扩展JFrame而不是JApplet然后它工作得很好。

这是我的代码:

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

2 个答案:

答案 0 :(得分:1)

您的JPanel阻止KeyListener

KeyListener只会在注册的组件具有可关注性且具有焦点时才会响应事件。

您应该使用Key Bindings代替。它们允许您注册对密钥的兴趣,即使它们注册的组件没有直接关注。

此外,您应该致电super.paint,事实上,您根本不应该覆盖顶级容器的paint方法。

创建自定义JPanel并覆盖它的paintComponent方法(确保致电super.paintComponent)并替换您要添加到applet的面板< / p>

工作示例

这是一个基于您提供的代码的工作示例,现在有编码缺失所以我不得不将其评论出来,但也有一大堆东西只是......很奇怪......

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

答案 1 :(得分:1)

不要覆盖JApplet的paint()方法。

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

自定义绘画在JPanel的paintComponent()方法中完成。