java - KeyBindings 在 JApplet 中无法正常工作

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

最佳答案

您的JPanel 阻止了KeyListener

KeyListener 仅当事件注册到的组件可聚焦且具有焦点时才会响应事件。

您应该使用Key Bindings反而。它们允许您注册对键的兴趣,即使它们注册的组件没有直接焦点。

此外,您应该调用 super.paint,事实上,您根本不应该重写顶级容器的 paint 方法。

创建一个自定义 JPanel 并覆盖它的 paintComponent 方法(确保调用 super.paintComponent)并替换为您要使用的面板添加到小程序

工作示例

这是一个基于您提供的代码的工作示例,现在缺少编码,所以我不得不将其注释掉,但是还有一大堆东西只是......奇怪......

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

关于java - KeyBindings 在 JApplet 中无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15966328/

相关文章:

flash - Flash/Java Applet 的 NPAPI 插件的替代品

java - 我们可以用 Java 模拟 Web 容器吗?

java - ArrayList 中的内容被修改

Java,使用compareTo方法在ToString中按字母顺序打印数组列表

JAVA:awt关于swing组件显示问题

java - 如何在不使用Applet的情况下加密浏览器中的文本字段?

java - Android - 相机在某些设备的后置摄像头上提供颠倒的数据

java - JTable 中图像的 html 问题

java - 使用 Java 禁用 Windows 自动更新

Java Applet 显示数据库中的名称