【问题标题】:Key adapter not working钥匙适配器不工作
【发布时间】:2013-08-30 15:50:14
【问题描述】:

我在我的 JPanel 类中创建了一个 KeyAdapter 类,并尝试使用 System.out.println(String par1); 调试点击

但它似乎不起作用......

这是课程:

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

有谁知道可能是什么问题?我已经在框架中设置了关键处理程序,并将框架设置为可聚焦..

提前致谢

~RyanS.

【问题讨论】:

    标签: java swing jpanel keylistener setfocus


    【解决方案1】:

    代码中不正确的事情(恕我直言):

    • 您在代码中访问图像的方式。考虑ImageIO,而不是使用ImageIcon 的构造函数,因为前者会通知你,以防出现问题。如需更多信息,请参阅Loading Image Icon Exception,了解更多信息。
    • KeyListeners 用于AWT,另一方面,Swing 使用KeyBindings
    • 之前,在任何JComponent 上设置背景最好先将所述JComponentopaque 属性设置为true。因为,opaque 属性通常依赖于使用的LookAndFeel
    • 尽可能避免使用setLayout(null)。请浏览Absolute Positioning 的第一段以获取更多信息:-)
    • ImageObserver 的使用已在 cmets 中提及。

    @camickr 的博客Motion Using the Keyboard 将再次增加您的知识,了解为什么KeyListeners 不被认为是更好的选择以及为什么KeyBindings 更适合此类需求:-)

    请看一下这个例子:

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

    【讨论】:

    • @rshah : 请按SPACE 并在Console 上查看文字LOL :-)
    【解决方案2】:

    将您的面板设置为可聚焦是不够的 - 面板无法单独获得焦点 - 您必须请求将焦点放在某种事件上。例如,您可以在面板中添加鼠标侦听器,并在单击时调用 panel.requestFocusInWindow()

    仅当您添加它的组件具有焦点时,键侦听器才会工作。

    【讨论】:

    • 究竟是什么不起作用?如果您单击带有这种焦点转移鼠标侦听器的面板并尝试按空格键 - 您将看到该键侦听器有效。
    • 所以我也需要鼠标监听器?
    • 您需要将焦点放在面板上,而不是某个按钮、字段或其他任何东西上。即使您将其设置为可聚焦,面板也不能仅靠自己获得焦点 - 您必须使用我提到的方法手动传递焦点。所以是的,鼠标监听器可以是手动将焦点传递到面板的选项。
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 2018-04-26
    • 2022-01-20
    • 2014-10-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多