【问题标题】:KeyBindings not working properly in JAppletKeyBindings 在 JApplet 中无法正常工作
【发布时间】:2013-04-12 08:16:49
【问题描述】:

该类用于在您按空格键时启动我制作的游戏,然后在游戏结束屏幕中按空格键时重新启动空格。当我按空格键并按预期开始游戏时,它第一次起作用,但是当我在屏幕上进入游戏并按空格键时没有任何反应。我尝试扩展 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();
        }
    }
}

【问题讨论】:

    标签: java swing applet key-bindings japplet


    【解决方案1】:

    你的JPanelKeyListener屏蔽

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-14
        • 2021-04-08
        • 2018-07-14
        相关资源
        最近更新 更多